Skip to content

Commit ef187f4

Browse files
authored
docs(sample): relocate native image sample from old repo (#1758)
* docs(sample): relocate native image sample from old repo
1 parent b6aed28 commit ef187f4

File tree

8 files changed

+517
-2
lines changed

8 files changed

+517
-2
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,13 @@ implementation 'com.google.cloud:google-cloud-spanner'
5656
If you are using Gradle without BOM, add this to your dependencies
5757

5858
```Groovy
59-
implementation 'com.google.cloud:google-cloud-spanner:6.25.4'
59+
implementation 'com.google.cloud:google-cloud-spanner:6.25.5'
6060
```
6161

6262
If you are using SBT, add this to your dependencies
6363

6464
```Scala
65-
libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.25.4"
65+
libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.25.5"
6666
```
6767

6868
## Authentication
@@ -240,6 +240,9 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-spanner/tree/
240240

241241
| Sample | Source Code | Try it |
242242
| --------------------------- | --------------------------------- | ------ |
243+
| Database Operations | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/DatabaseOperations.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/DatabaseOperations.java) |
244+
| Instance Operations | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/InstanceOperations.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/InstanceOperations.java) |
245+
| Native Image Spanner Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/native-image/src/main/java/com/example/spanner/NativeImageSpannerSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/native-image/src/main/java/com/example/spanner/NativeImageSpannerSample.java) |
243246
| Add Json Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddJsonColumnSample.java) |
244247
| Add Numeric Column Sample | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AddNumericColumnSample.java) |
245248
| Async Dml Example | [source code](https://github.com/googleapis/java-spanner/blob/main/samples/snippets/src/main/java/com/example/spanner/AsyncDmlExample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-spanner&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/spanner/AsyncDmlExample.java) |

samples/native-image/README.md

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# Spanner Sample Application with Native Image
2+
3+
This is a sample application which uses the Cloud Spanner client libraries and demonstrates compatibility with Native Image compilation.
4+
5+
The application creates a new Spanner instance and database, and it runs basic operations including queries and Spanner mutations.
6+
7+
## Setup Instructions
8+
9+
You will need to follow these prerequisite steps in order to run these samples:
10+
11+
1. If you have not already, [create a Google Cloud Platform Project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project).
12+
13+
2. Install the [Google Cloud SDK](https://cloud.google.com/sdk/) which will allow you to run the sample with your project's credentials.
14+
15+
Once installed, log in with Application Default Credentials using the following command:
16+
17+
```
18+
gcloud auth application-default login
19+
```
20+
21+
**Note:** Authenticating with Application Default Credentials is convenient to use during development, but we recommend [alternate methods of authentication](https://cloud.google.com/docs/authentication/production) during production use.
22+
23+
3. Install the GraalVM compiler.
24+
25+
You can follow the [official installation instructions](https://www.graalvm.org/docs/getting-started-with-graalvm/#install-graalvm) from the GraalVM website.
26+
After following the instructions, ensure that you install the Native Image extension installed by running:
27+
28+
```
29+
gu install native-image
30+
```
31+
32+
Once you finish following the instructions, verify that the default version of Java is set to the GraalVM version by running `java -version` in a terminal.
33+
34+
You will see something similar to the below output:
35+
36+
```
37+
$ java -version
38+
39+
openjdk version "11.0.15" 2022-04-19
40+
OpenJDK Runtime Environment GraalVM CE 22.1.0 (build 11.0.15+10-jvmci-22.1-b06)
41+
OpenJDK 64-Bit Server VM GraalVM CE 22.1.0 (build 11.0.15+10-jvmci-22.1-b06, mixed mode, sharing)
42+
43+
```
44+
## Run with Native Image Compilation
45+
46+
1. **(Optional)** If you wish to run the application against the [Spanner emulator](https://cloud.google.com/spanner/docs/emulator), make sure that you have the [Google Cloud SDK](https://cloud.google.com/sdk) installed.
47+
48+
In a new terminal window, start the emulator via `gcloud`:
49+
50+
```
51+
gcloud beta emulators spanner start
52+
```
53+
54+
You may leave the emulator running for now.
55+
In the next section, we will run the sample application against the Spanner emulator instsance.
56+
57+
2. Navigate to this directory and compile the application with the Native Image compiler.
58+
59+
```
60+
mvn package -P native -DskipTests
61+
```
62+
63+
3. **(Optional)** If you're using the emulator, export the `SPANNER_EMULATOR_HOST` as an environment variable in your terminal.
64+
65+
```
66+
export SPANNER_EMULATOR_HOST=localhost:9010
67+
```
68+
69+
The Spanner Client Libraries will detect this environment variable and will automatically connect to the emulator instance if this variable is set.
70+
71+
4. Run the application.
72+
73+
```
74+
./target/native-image
75+
```
76+
77+
5. The application will run through some basic Spanner operations and log some output statements.
78+
79+
```
80+
Running the Spanner Sample.
81+
Singers Registered in Spanner:
82+
Bob Loblaw
83+
Virginia Watson
84+
```
85+
86+
## Sample Integration test with Native Image Support
87+
88+
In order to run the sample integration test as a native image, call the following command:
89+
90+
```
91+
mvn test -Pnative
92+
```

samples/native-image/pom.xml

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<groupId>com.google.cloud</groupId>
5+
<artifactId>native-image</artifactId>
6+
<name>Native Image Sample</name>
7+
<url>https://github.com/googleapis/java-spanner</url>
8+
9+
<!--
10+
The parent pom defines common style checks and testing strategies for our samples.
11+
Removing or replacing it should not affect the execution of the samples in anyway.
12+
-->
13+
<parent>
14+
<groupId>com.google.cloud.samples</groupId>
15+
<artifactId>shared-configuration</artifactId>
16+
<version>1.2.0</version>
17+
</parent>
18+
19+
<properties>
20+
<!-- Java 8 because the Kokoro Sample test uses that Java version -->
21+
<maven.compiler.target>1.8</maven.compiler.target>
22+
<maven.compiler.source>1.8</maven.compiler.source>
23+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
24+
</properties>
25+
26+
<dependencyManagement>
27+
<dependencies>
28+
<dependency>
29+
<groupId>com.google.cloud</groupId>
30+
<artifactId>libraries-bom</artifactId>
31+
<version>25.2.0</version>
32+
<type>pom</type>
33+
<scope>import</scope>
34+
</dependency>
35+
</dependencies>
36+
</dependencyManagement>
37+
38+
<dependencies>
39+
<dependency>
40+
<groupId>com.google.cloud</groupId>
41+
<artifactId>google-cloud-spanner</artifactId>
42+
</dependency>
43+
44+
<dependency>
45+
<groupId>junit</groupId>
46+
<artifactId>junit</artifactId>
47+
<version>4.13.2</version>
48+
<scope>test</scope>
49+
</dependency>
50+
<dependency>
51+
<groupId>com.google.truth</groupId>
52+
<artifactId>truth</artifactId>
53+
<version>1.1.3</version>
54+
<scope>test</scope>
55+
</dependency>
56+
</dependencies>
57+
58+
<build>
59+
<!-- This plugin enables building the application to a JAR *not* using Native Image -->
60+
<plugins>
61+
<plugin>
62+
<groupId>org.apache.maven.plugins</groupId>
63+
<artifactId>maven-jar-plugin</artifactId>
64+
<version>3.2.2</version>
65+
<configuration>
66+
<archive>
67+
<manifest>
68+
<addClasspath>true</addClasspath>
69+
<classpathPrefix>dependency-jars/</classpathPrefix>
70+
<mainClass>com.example.spanner.NativeImageSpannerSample</mainClass>
71+
</manifest>
72+
</archive>
73+
</configuration>
74+
</plugin>
75+
<plugin>
76+
<groupId>org.apache.maven.plugins</groupId>
77+
<artifactId>maven-dependency-plugin</artifactId>
78+
<version>3.3.0</version>
79+
<executions>
80+
<execution>
81+
<id>copy-dependencies</id>
82+
<phase>package</phase>
83+
<goals>
84+
<goal>copy-dependencies</goal>
85+
</goals>
86+
<configuration>
87+
<outputDirectory>
88+
${project.build.directory}/dependency-jars/
89+
</outputDirectory>
90+
</configuration>
91+
</execution>
92+
</executions>
93+
</plugin>
94+
</plugins>
95+
</build>
96+
97+
<!-- Native Profile-->
98+
<profiles>
99+
<profile>
100+
<id>native</id>
101+
102+
<dependencies>
103+
<dependency>
104+
<groupId>org.junit.vintage</groupId>
105+
<artifactId>junit-vintage-engine</artifactId>
106+
<version>5.8.2</version>
107+
<scope>test</scope>
108+
</dependency>
109+
<dependency>
110+
<groupId>org.graalvm.buildtools</groupId>
111+
<artifactId>junit-platform-native</artifactId>
112+
<version>0.9.10</version>
113+
<scope>test</scope>
114+
</dependency>
115+
</dependencies>
116+
117+
<build>
118+
<plugins>
119+
<plugin>
120+
<groupId>org.apache.maven.plugins</groupId>
121+
<artifactId>maven-surefire-plugin
122+
</artifactId> <!-- Must use older version of surefire plugin for native-image testing. -->
123+
<version>2.22.2</version>
124+
<configuration>
125+
<includes>
126+
<include>**/*IT</include>
127+
</includes>
128+
</configuration>
129+
</plugin>
130+
<plugin>
131+
<groupId>org.graalvm.buildtools</groupId>
132+
<artifactId>native-maven-plugin</artifactId>
133+
<version>0.9.9</version>
134+
<extensions>true</extensions>
135+
<configuration>
136+
<mainClass>com.example.spanner.NativeImageSpannerSample</mainClass>
137+
<buildArgs>
138+
<buildArg>--no-fallback</buildArg>
139+
<buildArg>--no-server</buildArg>
140+
</buildArgs>
141+
</configuration>
142+
<executions>
143+
<execution>
144+
<id>build-native</id>
145+
<goals>
146+
<goal>build</goal>
147+
<goal>test</goal>
148+
</goals>
149+
<phase>package</phase>
150+
</execution>
151+
<execution>
152+
<id>test-native</id>
153+
<goals>
154+
<goal>test</goal>
155+
</goals>
156+
<phase>test</phase>
157+
</execution>
158+
</executions>
159+
</plugin>
160+
</plugins>
161+
</build>
162+
</profile>
163+
</profiles>
164+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2022 Google LLC
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.spanner;
18+
19+
import com.google.cloud.spanner.Database;
20+
import com.google.cloud.spanner.DatabaseAdminClient;
21+
import com.google.cloud.spanner.DatabaseClient;
22+
import com.google.cloud.spanner.KeySet;
23+
import com.google.cloud.spanner.Mutation;
24+
import com.google.cloud.spanner.ResultSet;
25+
import com.google.cloud.spanner.Statement;
26+
import com.google.common.collect.ImmutableList;
27+
import java.util.Collections;
28+
import java.util.List;
29+
30+
/** Helper methods to manage Spanner Databases. */
31+
public class DatabaseOperations {
32+
33+
private static final List<String> DDL_STATEMENTS =
34+
ImmutableList.of(
35+
"CREATE TABLE Singers (SingerId INT64 NOT NULL, FirstName "
36+
+ "STRING(1024), LastName STRING(1024)) PRIMARY KEY (SingerId)");
37+
38+
static void createDatabase(
39+
DatabaseAdminClient databaseAdminClient, String instanceId, String databaseId) {
40+
41+
if (databaseExists(databaseAdminClient, instanceId, databaseId)) {
42+
databaseAdminClient.dropDatabase(instanceId, databaseId);
43+
}
44+
databaseAdminClient.createDatabase(instanceId, databaseId, DDL_STATEMENTS);
45+
}
46+
47+
static boolean databaseExists(
48+
DatabaseAdminClient databaseAdminClient, String instanceId, String databaseId) {
49+
50+
for (Database database : databaseAdminClient.listDatabases(instanceId).iterateAll()) {
51+
if (databaseId.equals(database.getId().getDatabase())) {
52+
return true;
53+
}
54+
}
55+
return false;
56+
}
57+
58+
static void insertUsingDml(DatabaseClient dbClient) {
59+
dbClient
60+
.readWriteTransaction()
61+
.run(
62+
transaction -> {
63+
String sql =
64+
"INSERT INTO Singers (SingerId, FirstName, LastName) "
65+
+ " VALUES (10, 'Virginia', 'Watson')";
66+
transaction.executeUpdate(Statement.of(sql));
67+
return null;
68+
});
69+
}
70+
71+
static void insertUsingMutation(DatabaseClient dbClient) {
72+
Mutation mutation =
73+
Mutation.newInsertBuilder("Singers")
74+
.set("SingerId")
75+
.to(12)
76+
.set("FirstName")
77+
.to("Bob")
78+
.set("LastName")
79+
.to("Loblaw")
80+
.build();
81+
dbClient.write(Collections.singletonList(mutation));
82+
}
83+
84+
static ResultSet performRead(DatabaseClient dbClient) {
85+
return dbClient.singleUse().executeQuery(Statement.of("SELECT * FROM Singers"));
86+
}
87+
88+
static void deleteDatabase(DatabaseClient dbClient) {
89+
dbClient.write(Collections.singletonList(Mutation.delete("Singers", KeySet.all())));
90+
System.out.println("Records deleted.");
91+
}
92+
}

0 commit comments

Comments
 (0)