Skip to content

Commit f68a34b

Browse files
committed
Add App Engine Datastore raw APIs sample.
These samples are pulled from the "projection query" https://cloud.google.com/appengine/docs/java/datastore/projectionqueries and "structuring for strong consistency" https://cloud.google.com/appengine/docs/java/datastore/structuring_for_strong_consistency pages. I will add additional code to this sample as I convert the other pages, as well.
1 parent e486daf commit f68a34b

21 files changed

+1380
-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: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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+
<plugin>
107+
<groupId>org.apache.maven.plugins</groupId>
108+
<version>3.3</version>
109+
<artifactId>maven-compiler-plugin</artifactId>
110+
<configuration>
111+
<source>1.7</source>
112+
<target>1.7</target>
113+
</configuration>
114+
</plugin>
115+
<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
116+
<plugin>
117+
<groupId>com.google.appengine</groupId>
118+
<artifactId>appengine-maven-plugin</artifactId>
119+
<version>${appengine.sdk.version}</version>
120+
</plugin>
121+
</plugins>
122+
</build>
123+
</project>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
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.users.User;
24+
import com.google.appengine.api.users.UserService;
25+
import com.google.common.collect.ImmutableList;
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 is meant to be subclassed to demonstrate different storage structures in Datastore.
34+
*/
35+
abstract class AbstractGuestbook {
36+
private final DatastoreService datastore;
37+
private final UserService userService;
38+
private final Clock clock;
39+
40+
AbstractGuestbook(DatastoreService datastore, UserService userService, Clock clock) {
41+
this.datastore = datastore;
42+
this.userService = userService;
43+
this.clock = clock;
44+
}
45+
46+
/**
47+
* Appends a new greeting to the guestbook and returns the {@link Entity} that was created.
48+
*/
49+
public Greeting appendGreeting(String content) {
50+
Greeting greeting =
51+
Greeting.create(
52+
createGreeting(
53+
datastore,
54+
userService.getCurrentUser(),
55+
clock.now().toDate(),
56+
content));
57+
return greeting;
58+
}
59+
60+
/**
61+
* Write a greeting to Datastore.
62+
*/
63+
protected abstract Entity createGreeting(
64+
DatastoreService datastore,
65+
User user,
66+
Date date,
67+
String content);
68+
69+
/**
70+
* Return a list of the most recent greetings.
71+
*/
72+
public List<Greeting> listGreetings() {
73+
ImmutableList.Builder<Greeting> greetings = ImmutableList.builder();
74+
for (Entity entity : listGreetingEntities(datastore)) {
75+
greetings.add(Greeting.create(entity));
76+
}
77+
return greetings.build();
78+
}
79+
80+
/**
81+
* Return a list of the most recent greetings.
82+
*/
83+
protected abstract List<Entity> listGreetingEntities(DatastoreService datastore);
84+
}
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+
}

0 commit comments

Comments
 (0)