Skip to content

Commit 0dd0927

Browse files
committed
Merge pull request #171 from GoogleCloudPlatform/datastore
Add App Engine Datastore raw APIs sample.
2 parents c32e16d + c2091ae commit 0dd0927

21 files changed

+1330
-0
lines changed

appengine/datastore/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Google Cloud Datastore Sample
2+
3+
This sample demonstrates how to use [Google Cloud Datastore][java-datastore]
4+
from [Google App Engine standard environment][ae-docs].
5+
6+
[java-datastore]: https://cloud.google.com/appengine/docs/java/datastore/
7+
[ae-docs]: https://cloud.google.com/appengine/docs/java/
8+
9+
## Setup
10+
1. Update the `<application>` tag in `src/main/webapp/WEB-INF/appengine-web.xml`
11+
with your project name.
12+
1. Update the `<version>` tag in `src/main/webapp/WEB-INF/appengine-web.xml`
13+
with your version name.
14+
15+
## Running locally
16+
$ mvn appengine:devserver
17+
18+
## Deploying
19+
$ mvn appengine:update

appengine/datastore/pom.xml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<!--
2+
Copyright 2016 Google Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<project>
17+
<modelVersion>4.0.0</modelVersion>
18+
<packaging>war</packaging>
19+
<version>1.0-SNAPSHOT</version>
20+
<groupId>com.example.appengine</groupId>
21+
<artifactId>appengine-datastore</artifactId>
22+
<parent>
23+
<groupId>com.google.cloud</groupId>
24+
<artifactId>doc-samples</artifactId>
25+
<version>1.0.0</version>
26+
<relativePath>../..</relativePath>
27+
</parent>
28+
<dependencies>
29+
<dependency>
30+
<groupId>com.google.appengine</groupId>
31+
<artifactId>appengine-api-1.0-sdk</artifactId>
32+
<version>${appengine.sdk.version}</version>
33+
</dependency>
34+
<dependency>
35+
<groupId>com.google.auto.value</groupId>
36+
<artifactId>auto-value</artifactId>
37+
<version>1.2</version>
38+
<scope>provided</scope>
39+
</dependency>
40+
<dependency>
41+
<groupId>com.google.code.findbugs</groupId>
42+
<artifactId>jsr305</artifactId> <!-- @Nullable annotations -->
43+
<version>3.0.1</version>
44+
</dependency>
45+
46+
<dependency>
47+
<groupId>com.google.guava</groupId>
48+
<artifactId>guava</artifactId>
49+
<version>19.0</version>
50+
</dependency>
51+
52+
<dependency>
53+
<groupId>javax.servlet</groupId>
54+
<artifactId>servlet-api</artifactId>
55+
<type>jar</type>
56+
<scope>provided</scope>
57+
</dependency>
58+
<dependency>
59+
<groupId>joda-time</groupId>
60+
<artifactId>joda-time</artifactId>
61+
<version>2.9.3</version>
62+
</dependency>
63+
64+
<!-- Test Dependencies -->
65+
<dependency>
66+
<groupId>junit</groupId>
67+
<artifactId>junit</artifactId>
68+
<version>4.10</version>
69+
<scope>test</scope>
70+
</dependency>
71+
<dependency>
72+
<groupId>org.mockito</groupId>
73+
<artifactId>mockito-all</artifactId>
74+
<version>1.10.19</version>
75+
<scope>test</scope>
76+
</dependency>
77+
<dependency>
78+
<groupId>com.google.appengine</groupId>
79+
<artifactId>appengine-testing</artifactId>
80+
<version>${appengine.sdk.version}</version>
81+
<scope>test</scope>
82+
</dependency>
83+
<dependency>
84+
<groupId>com.google.appengine</groupId>
85+
<artifactId>appengine-api-stubs</artifactId>
86+
<version>${appengine.sdk.version}</version>
87+
<scope>test</scope>
88+
</dependency>
89+
<dependency>
90+
<groupId>com.google.appengine</groupId>
91+
<artifactId>appengine-tools-sdk</artifactId>
92+
<version>${appengine.sdk.version}</version>
93+
<scope>test</scope>
94+
</dependency>
95+
<dependency>
96+
<groupId>com.google.truth</groupId>
97+
<artifactId>truth</artifactId>
98+
<version>0.28</version>
99+
<scope>test</scope>
100+
</dependency>
101+
</dependencies>
102+
<build>
103+
<!-- for hot reload of the web application -->
104+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory>
105+
<plugins>
106+
<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
107+
<plugin>
108+
<groupId>com.google.appengine</groupId>
109+
<artifactId>appengine-maven-plugin</artifactId>
110+
<version>${appengine.sdk.version}</version>
111+
</plugin>
112+
</plugins>
113+
</build>
114+
</project>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine;
18+
19+
import com.example.time.Clock;
20+
21+
import com.google.appengine.api.datastore.DatastoreService;
22+
import com.google.appengine.api.datastore.DatastoreServiceFactory;
23+
import com.google.appengine.api.datastore.Entity;
24+
import com.google.appengine.api.users.User;
25+
import com.google.appengine.api.users.UserService;
26+
import com.google.appengine.api.users.UserServiceFactory;
27+
import com.google.common.collect.ImmutableList;
28+
29+
import java.util.Date;
30+
import java.util.List;
31+
32+
/**
33+
* A log of notes left by users.
34+
*
35+
* <p>This is meant to be subclassed to demonstrate different storage structures in Datastore.
36+
*/
37+
abstract class AbstractGuestbook {
38+
private final DatastoreService datastore;
39+
private final UserService userService;
40+
private final Clock clock;
41+
42+
AbstractGuestbook(Clock clock) {
43+
this.datastore = DatastoreServiceFactory.getDatastoreService();
44+
this.userService = UserServiceFactory.getUserService();
45+
this.clock = clock;
46+
}
47+
48+
/**
49+
* Appends a new greeting to the guestbook and returns the {@link Entity} that was created.
50+
*/
51+
public Greeting appendGreeting(String content) {
52+
Greeting greeting =
53+
Greeting.create(
54+
createGreeting(
55+
datastore,
56+
userService.getCurrentUser(),
57+
clock.now().toDate(),
58+
content));
59+
return greeting;
60+
}
61+
62+
/**
63+
* Write a greeting to Datastore.
64+
*/
65+
protected abstract Entity createGreeting(
66+
DatastoreService datastore, User user, Date date, String content);
67+
68+
/**
69+
* Return a list of the most recent greetings.
70+
*/
71+
public List<Greeting> listGreetings() {
72+
ImmutableList.Builder<Greeting> greetings = ImmutableList.builder();
73+
for (Entity entity : listGreetingEntities(datastore)) {
74+
greetings.add(Greeting.create(entity));
75+
}
76+
return greetings.build();
77+
}
78+
79+
/**
80+
* Return a list of the most recent greetings.
81+
*/
82+
protected abstract List<Entity> listGreetingEntities(DatastoreService datastore);
83+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine;
18+
19+
import java.io.IOException;
20+
21+
import javax.servlet.ServletException;
22+
import javax.servlet.http.HttpServlet;
23+
import javax.servlet.http.HttpServletRequest;
24+
import javax.servlet.http.HttpServletResponse;
25+
26+
abstract class AbstractGuestbookServlet extends HttpServlet {
27+
private final AbstractGuestbook guestbook;
28+
29+
public AbstractGuestbookServlet(AbstractGuestbook guestbook) {
30+
this.guestbook = guestbook;
31+
}
32+
33+
private void renderGuestbook(HttpServletRequest req, HttpServletResponse resp)
34+
throws IOException, ServletException {
35+
resp.setContentType("text/html");
36+
resp.setCharacterEncoding("UTF-8");
37+
req.setAttribute("greetings", guestbook.listGreetings());
38+
req.getRequestDispatcher("/guestbook.jsp").forward(req, resp);
39+
}
40+
41+
@Override
42+
public void doGet(HttpServletRequest req, HttpServletResponse resp)
43+
throws IOException, ServletException {
44+
renderGuestbook(req, resp);
45+
}
46+
47+
@Override
48+
public void doPost(HttpServletRequest req, HttpServletResponse resp)
49+
throws IOException, ServletException {
50+
String content = req.getParameter("content");
51+
if (content == null || content.isEmpty()) {
52+
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "missing content");
53+
return;
54+
}
55+
guestbook.appendGreeting(content);
56+
renderGuestbook(req, resp);
57+
}
58+
}
59+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine;
18+
19+
import com.google.appengine.api.datastore.Entity;
20+
import com.google.appengine.api.users.User;
21+
import com.google.auto.value.AutoValue;
22+
import org.joda.time.Instant;
23+
24+
import java.util.Date;
25+
26+
import javax.annotation.Nullable;
27+
28+
@AutoValue
29+
public abstract class Greeting {
30+
static Greeting create(Entity entity) {
31+
User user = (User) entity.getProperty("user");
32+
Instant date = new Instant((Date) entity.getProperty("date"));
33+
String content = (String) entity.getProperty("content");
34+
return new AutoValue_Greeting(user, date, content);
35+
}
36+
37+
@Nullable
38+
public abstract User getUser();
39+
40+
public abstract Instant getDate();
41+
42+
public abstract String getContent();
43+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine;
18+
19+
import com.example.time.Clock;
20+
21+
import com.google.appengine.api.datastore.DatastoreService;
22+
import com.google.appengine.api.datastore.Entity;
23+
import com.google.appengine.api.datastore.FetchOptions;
24+
import com.google.appengine.api.datastore.Query;
25+
import com.google.appengine.api.users.User;
26+
27+
import java.util.Date;
28+
import java.util.List;
29+
30+
/**
31+
* A log of notes left by users.
32+
*
33+
* <p>This demonstrates the use of Google Cloud Datastore using the App Engine
34+
* APIs. See the
35+
* <a href="https://cloud.google.com/appengine/docs/java/datastore/">documentation</a>
36+
* for more information.
37+
*/
38+
class Guestbook extends AbstractGuestbook {
39+
Guestbook(Clock clock) {
40+
super(clock);
41+
}
42+
43+
@Override
44+
protected Entity createGreeting(
45+
DatastoreService datastore, User user, Date date, String content) {
46+
// No parent key specified, so Greeting is a root entity.
47+
Entity greeting = new Entity("Greeting");
48+
greeting.setProperty("user", user);
49+
greeting.setProperty("date", date);
50+
greeting.setProperty("content", content);
51+
52+
datastore.put(greeting);
53+
return greeting;
54+
}
55+
56+
@Override
57+
protected List<Entity> listGreetingEntities(DatastoreService datastore) {
58+
Query query =
59+
new Query("Greeting")
60+
.addSort("date", Query.SortDirection.DESCENDING);
61+
return datastore.prepare(query)
62+
.asList(FetchOptions.Builder.withLimit(10));
63+
}
64+
65+
66+
}

0 commit comments

Comments
 (0)