Skip to content

Commit bdd8a8a

Browse files
authored
adding java8 spanner sample (GoogleCloudPlatform#711)
1 parent bfe3cce commit bdd8a8a

File tree

7 files changed

+822
-2
lines changed

7 files changed

+822
-2
lines changed

appengine-java8/pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,16 @@
6464
<module>multitenancy</module>
6565
<module>oauth2</module>
6666
<module>requests</module>
67-
<module>search</module>
68-
<module>sendgrid</module>
6967

7068
<module>remote-client</module>
7169
<module>remote-server</module>
7270

71+
<module>search</module>
72+
73+
<module>sendgrid</module>
74+
75+
<module>spanner</module>
76+
7377
<module>static-files</module>
7478

7579
<module>taskqueues-deferred</module>

appengine-java8/spanner/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Google Cloud Spanner Sample
2+
3+
This sample demonstrates how to use [Google Cloud Spanner][spanner-docs]
4+
from [Google App Engine standard environment][ae-docs].
5+
6+
[spanner-docs]: https://cloud.google.com/spanner/docs/
7+
[ae-docs]: https://cloud.google.com/appengine/docs/java/
8+
9+
10+
## Setup
11+
- Install the [Google Cloud SDK](https://cloud.google.com/sdk/) and run:
12+
```
13+
gcloud init
14+
```
15+
If this is your first time creating an App engine application:
16+
```
17+
gcloud app create
18+
```
19+
- [Create a Spanner instance](https://cloud.google.com/spanner/docs/quickstart-console#create_an_instance).
20+
21+
- Update `SPANNER_INSTANCE` value in `[appengine-web.xml](src/main/webapp/WEB-INF/appengine-web.xml).
22+
23+
## Endpoints
24+
- `/spanner` : will run sample operations against the spanner instance in order. Individual tasks can be run
25+
using the `task` query parameter. See [SpannerTasks](src/main/java/com/example/appengine/spanner/SpannerTasks.java)
26+
for supported set of tasks.
27+
Note : by default all the spanner example operations run in order, this operation may take a while to return.
28+
29+
## Running locally
30+
- Authorize the local application:
31+
```
32+
gcloud auth application-default login
33+
```
34+
You may also [create and use service account credentials](https://cloud.google.com/docs/authentication/getting-started#creating_the_service_account).
35+
36+
- App Engine Maven plugins do not work correctly for this sample for local testing.
37+
Here is the [tracking issue](https://github.com/GoogleCloudPlatform/google-cloud-java/issues/2155).
38+
As a workaround to run locally, this sample uses the [Maven Jetty plugin](http://www.eclipse.org/jetty/documentation/9.4.x/jetty-maven-plugin.html).
39+
```
40+
mvn -DSPANNER_INSTANCE=my-spanner-instance jetty:run
41+
```
42+
43+
To see the results of the local application, open
44+
[http://localhost:8080/run](http://localhost:8080/run) in a web browser.
45+
Note : by default all the spanner example operations run in order, this operation may take a while to show results.
46+
47+
## Deploying
48+
49+
$ mvn clean appengine:deploy
50+
51+
To see the results of the deployed sample application, open
52+
`https://spanner-dot-PROJECTID.appspot.com/run` in a web browser.
53+
Note : by default all the spanner example operations run in order, this operation may take a while to show results.
54+

appengine-java8/spanner/pom.xml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright 2017 Google Inc.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<groupId>com.example.appengine</groupId>
21+
<modelVersion>4.0.0</modelVersion>
22+
<artifactId>appengine-spanner-j8</artifactId>
23+
<version>1.0-SNAPSHOT</version>
24+
<packaging>war</packaging>
25+
<properties>
26+
<failOnMissingWebXml>false</failOnMissingWebXml>
27+
</properties>
28+
29+
<parent>
30+
<artifactId>appengine-java8-samples</artifactId>
31+
<groupId>com.google.cloud</groupId>
32+
<version>1.0.0</version>
33+
<relativePath>..</relativePath>
34+
</parent>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>com.google.cloud</groupId>
39+
<artifactId>google-cloud-spanner</artifactId>
40+
<version>0.19.0-beta</version>
41+
</dependency>
42+
<dependency>
43+
<groupId>javax.servlet</groupId>
44+
<artifactId>javax.servlet-api</artifactId>
45+
<version>3.1.0</version>
46+
<scope>provided</scope>
47+
</dependency>
48+
<dependency>
49+
<groupId>com.google.appengine</groupId>
50+
<artifactId>appengine-api-1.0-sdk</artifactId>
51+
<version>1.9.53</version>
52+
</dependency>
53+
</dependencies>
54+
55+
<build>
56+
<outputDirectory>
57+
${project.build.directory}/${project.build.finalName}/WEB-INF/classes
58+
</outputDirectory>
59+
60+
<plugins>
61+
<!-- START Using Jetty plugin as workaround for local testing.
62+
https://github.com/GoogleCloudPlatform/google-cloud-java/issues/2155:
63+
This sample does not work with the AppEngine Maven Plugins for local testing
64+
-->
65+
<plugin>
66+
<groupId>org.eclipse.jetty</groupId>
67+
<artifactId>jetty-maven-plugin</artifactId>
68+
<version>9.4.6.v20170531</version>
69+
</plugin>
70+
<!-- END -->
71+
72+
<plugin>
73+
<groupId>org.apache.maven.plugins</groupId>
74+
<version>3.5.1</version>
75+
<artifactId>maven-compiler-plugin</artifactId>
76+
<configuration>
77+
<source>1.8</source>
78+
<target>1.8</target>
79+
</configuration>
80+
</plugin>
81+
<plugin>
82+
<groupId>com.google.cloud.tools</groupId>
83+
<artifactId>appengine-maven-plugin</artifactId>
84+
<version>1.3.1</version>
85+
<configuration>
86+
<deploy.promote>true</deploy.promote>
87+
<deploy.stopPreviousVersion>true</deploy.stopPreviousVersion>
88+
</configuration>
89+
</plugin>
90+
</plugins>
91+
</build>
92+
</project>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Copyright 2017 Google Inc.
3+
*
4+
* <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5+
* except in compliance with the License. You may obtain a copy of the License at
6+
*
7+
* <p>http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
10+
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
* express or implied. See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
package com.example.appengine.spanner;
15+
16+
import com.google.cloud.spanner.DatabaseAdminClient;
17+
import com.google.cloud.spanner.DatabaseClient;
18+
import com.google.cloud.spanner.DatabaseId;
19+
import com.google.cloud.spanner.Spanner;
20+
import com.google.cloud.spanner.SpannerOptions;
21+
import java.io.IOException;
22+
import java.util.UUID;
23+
import javax.servlet.ServletContext;
24+
import javax.servlet.ServletContextEvent;
25+
import javax.servlet.ServletContextListener;
26+
import javax.servlet.annotation.WebListener;
27+
28+
// With @WebListener annotation the webapp/WEB-INF/web.xml is no longer required.
29+
@WebListener
30+
public class SpannerClient implements ServletContextListener {
31+
32+
private static String PROJECT_ID;
33+
private static String INSTANCE_ID;
34+
private static String DATABASE_ID;
35+
36+
// The initial connection can be an expensive operation -- We cache this Connection
37+
// to speed things up. For this sample, keeping them here is a good idea, for
38+
// your application, you may wish to keep this somewhere else.
39+
private static Spanner spanner = null;
40+
private static DatabaseAdminClient databaseAdminClient = null;
41+
private static DatabaseClient databaseClient = null;
42+
43+
private static ServletContext sc;
44+
45+
private static void connect() throws IOException {
46+
if (INSTANCE_ID == null) {
47+
if (sc != null) {
48+
sc.log("environment variable SPANNER_INSTANCE need to be defined.");
49+
}
50+
return;
51+
}
52+
SpannerOptions options = SpannerOptions.newBuilder().build();
53+
PROJECT_ID = options.getProjectId();
54+
spanner = options.getService();
55+
databaseAdminClient = spanner.getDatabaseAdminClient();
56+
}
57+
58+
static DatabaseAdminClient getDatabaseAdminClient() {
59+
if (databaseAdminClient == null) {
60+
try {
61+
connect();
62+
} catch (IOException e) {
63+
if (sc != null) {
64+
sc.log("getDatabaseAdminClient ", e);
65+
}
66+
}
67+
}
68+
if (databaseAdminClient == null) {
69+
if (sc != null) {
70+
sc.log("Spanner : Unable to connect");
71+
}
72+
}
73+
return databaseAdminClient;
74+
}
75+
76+
static DatabaseClient getDatabaseClient() {
77+
if (databaseClient == null) {
78+
databaseClient =
79+
spanner.getDatabaseClient(DatabaseId.of(PROJECT_ID, INSTANCE_ID, DATABASE_ID));
80+
}
81+
return databaseClient;
82+
}
83+
84+
@Override
85+
public void contextInitialized(ServletContextEvent event) {
86+
if (event != null) {
87+
sc = event.getServletContext();
88+
if (INSTANCE_ID == null) {
89+
INSTANCE_ID = sc.getInitParameter("SPANNER_INSTANCE");
90+
}
91+
}
92+
//try system properties
93+
if (INSTANCE_ID == null) {
94+
INSTANCE_ID = System.getProperty("SPANNER_INSTANCE");
95+
}
96+
97+
if (DATABASE_ID == null) {
98+
DATABASE_ID = "db-" + UUID.randomUUID().toString().substring(0, 25);
99+
}
100+
101+
try {
102+
connect();
103+
} catch (IOException e) {
104+
if (sc != null) {
105+
sc.log("SpannerConnection - connect ", e);
106+
}
107+
}
108+
if (databaseAdminClient == null) {
109+
if (sc != null) {
110+
sc.log("SpannerConnection - No Connection");
111+
}
112+
}
113+
if (sc != null) {
114+
sc.log("ctx Initialized: " + INSTANCE_ID + " " + DATABASE_ID);
115+
}
116+
}
117+
118+
@Override
119+
public void contextDestroyed(ServletContextEvent servletContextEvent) {
120+
// App Engine does not currently invoke this method.
121+
databaseAdminClient = null;
122+
}
123+
124+
static String getInstanceId() {
125+
return INSTANCE_ID;
126+
}
127+
128+
static String getDatabaseId() {
129+
return DATABASE_ID;
130+
}
131+
}

0 commit comments

Comments
 (0)