-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs(sample): Add sample for native image support in Datastore (#640)
* docs(sample): add native image sample for Datastore
- Loading branch information
Showing
5 changed files
with
456 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Datastore Sample Application with Native Image | ||
|
||
This application uses the [Google Cloud Datastore client library](https://cloud.google.com/datastore/docs/reference/libraries) and is compatible with Native Image compilation. | ||
|
||
This sample runs through some basic operations of creating/deleting entities, running queries, and running transaction code. | ||
|
||
## Setup Instructions | ||
|
||
You will need to follow these prerequisite steps in order to run the samples: | ||
|
||
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). | ||
|
||
2. Install the [Google Cloud SDK](https://cloud.google.com/sdk/) which will allow you to run the sample with your project's credentials. | ||
|
||
Once installed, log in with Application Default Credentials using the following command: | ||
|
||
``` | ||
gcloud auth application-default login | ||
``` | ||
|
||
**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. | ||
|
||
3. Install the GraalVM compiler. | ||
|
||
You can follow the [official installation instructions](https://www.graalvm.org/docs/getting-started/#install-graalvm) from the GraalVM website. | ||
After following the instructions, ensure that you install the native image extension installed by running: | ||
|
||
``` | ||
gu install native-image | ||
``` | ||
|
||
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. | ||
|
||
You will see something similar to the below output: | ||
|
||
``` | ||
$ java -version | ||
openjdk version "11.0.7" 2020-04-14 | ||
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02) | ||
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing) | ||
``` | ||
## Sample | ||
1. **(Optional)** If you wish to run the application against the [Datastore emulator](https://cloud.google.com/sdk/gcloud/reference/beta/emulators/datastore), ensure that you have the [Google Cloud SDK](https://cloud.google.com/sdk) installed. | ||
|
||
In a new terminal window, start the emulator via `gcloud`: | ||
|
||
``` | ||
gcloud beta emulators datastore start --host-port=localhost:9010 | ||
``` | ||
|
||
Leave the emulator running in this terminal for now. | ||
In the next section, we will run the sample application against the Datastore emulator instance. | ||
|
||
2. Navigate to this directory and compile the application with the native image compiler. | ||
|
||
``` | ||
mvn package -P native -DskipTests | ||
``` | ||
|
||
3. **(Optional)** If you're using the emulator, export the `DATASTORE_EMULATOR_HOST` as an environment variable in your terminal. | ||
|
||
``` | ||
export DATASTORE_EMULATOR_HOST=localhost:9010 | ||
``` | ||
|
||
The Datastore Client Libraries will detect this environment variable and automatically connect to the emulator instance if this variable is set. | ||
|
||
4. Run the application. | ||
|
||
``` | ||
./target/native-image-sample | ||
``` | ||
|
||
5. The application will run through some basic Datastore operations and log some output statements. | ||
|
||
``` | ||
Successfully added entity. | ||
Reading entity: 1cf34cc1-2b8a-4945-9fc4-058f03dcd08e | ||
Successfully deleted entity: 1cf34cc1-2b8a-4945-9fc4-058f03dcd08e | ||
Run fake transaction code. | ||
Found entity: | ||
name=de4f36f4-3936-4252-98d3-e0d56d485254 | ||
kind=test-kind | ||
namespace=nativeimage-test-namespace | ||
properties={description=StringValue{valueType=STRING, excludeFromIndexes=false, meaning=0, value=hello world}} | ||
Ran transaction callable. | ||
``` | ||
|
||
### Sample Integration test with Native Image Support | ||
|
||
In order to run the sample integration test as a native image, call the following command: | ||
|
||
``` | ||
mvn test -Pnative | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
<?xml version='1.0' encoding='UTF-8'?> | ||
<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"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>com.example.datastore</groupId> | ||
<artifactId>native-image-sample</artifactId> | ||
<name>Native Image Sample</name> | ||
<url>https://github.com/googleapis/java-datastore</url> | ||
|
||
<!-- | ||
The parent pom defines common style checks and testing strategies for our samples. | ||
Removing or replacing it should not affect the execution of the samples in anyway. | ||
--> | ||
<parent> | ||
<groupId>com.google.cloud.samples</groupId> | ||
<artifactId>shared-configuration</artifactId> | ||
<version>1.2.0</version> | ||
</parent> | ||
|
||
<properties> | ||
<maven.compiler.target>11</maven.compiler.target> | ||
<maven.compiler.source>11</maven.compiler.source> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>com.google.cloud</groupId> | ||
<artifactId>libraries-bom</artifactId> | ||
<version>24.2.0</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.google.cloud</groupId> | ||
<artifactId>google-cloud-datastore</artifactId> | ||
</dependency> | ||
|
||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.13.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.truth</groupId> | ||
<artifactId>truth</artifactId> | ||
<version>1.1.3</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<configuration> | ||
<archive> | ||
<manifest> | ||
<mainClass>com.example.datastore.NativeImageDatastoreSample | ||
</mainClass> | ||
</manifest> | ||
</archive> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
<!-- Native Profile--> | ||
<profiles> | ||
<profile> | ||
<id>native</id> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.google.cloud</groupId> | ||
<artifactId>native-image-support</artifactId> | ||
<version>0.12.4</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.vintage</groupId> | ||
<artifactId>junit-vintage-engine</artifactId> | ||
<version>5.8.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.graalvm.buildtools</groupId> | ||
<artifactId>junit-platform-native</artifactId> | ||
<version>0.9.9</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-surefire-plugin | ||
</artifactId> <!-- Must use older version of surefire plugin for native-image testing. --> | ||
<version>2.22.2</version> | ||
<configuration> | ||
<includes> | ||
<include>**/IT*</include> | ||
</includes> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.graalvm.buildtools</groupId> | ||
<artifactId>native-maven-plugin</artifactId> | ||
<version>0.9.9</version> | ||
<extensions>true</extensions> | ||
<configuration> | ||
<mainClass>com.example.datastore.NativeImageDatastoreSample | ||
</mainClass> | ||
<buildArgs> | ||
<buildArg>--no-fallback</buildArg> | ||
<buildArg>--no-server</buildArg> | ||
</buildArgs> | ||
</configuration> | ||
<executions> | ||
<execution> | ||
<id>build-native</id> | ||
<goals> | ||
<goal>build</goal> | ||
<goal>test</goal> | ||
</goals> | ||
<phase>package</phase> | ||
</execution> | ||
<execution> | ||
<id>test-native</id> | ||
<goals> | ||
<goal>test</goal> | ||
</goals> | ||
<phase>test</phase> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |
137 changes: 137 additions & 0 deletions
137
...s/native-image-sample/src/main/java/com/example/datastore/NativeImageDatastoreSample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* Copyright 2020-2021 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.example.datastore; | ||
|
||
import com.google.cloud.datastore.Datastore; | ||
import com.google.cloud.datastore.DatastoreOptions; | ||
import com.google.cloud.datastore.Entity; | ||
import com.google.cloud.datastore.Key; | ||
import com.google.cloud.datastore.Query; | ||
import com.google.cloud.datastore.QueryResults; | ||
import com.google.cloud.datastore.StructuredQuery; | ||
import com.google.cloud.datastore.Transaction; | ||
import java.time.Duration; | ||
import java.time.Instant; | ||
import java.util.UUID; | ||
|
||
/** | ||
* Sample Datastore Application. | ||
*/ | ||
public class NativeImageDatastoreSample { | ||
|
||
/* Datastore namespace where entities will be created. */ | ||
private static final String TEST_NAMESPACE = "nativeimage-test-namespace"; | ||
|
||
/* Datastore kind used. */ | ||
private static final String TEST_KIND = "test-kind"; | ||
|
||
/** | ||
* Entrypoint to the Datastore sample application. | ||
*/ | ||
public static void main(String[] args) { | ||
Instant startTime = Instant.now(); | ||
Datastore datastore = DatastoreOptions.getDefaultInstance().getService(); | ||
|
||
String testId = UUID.randomUUID().toString(); | ||
|
||
addEntity(datastore, testId); | ||
getEntity(datastore, testId); | ||
deleteEntity(datastore, testId); | ||
|
||
runTransaction(datastore); | ||
|
||
String id = UUID.randomUUID().toString(); | ||
Key key = createKey(datastore, id); | ||
runTransactionCallable(datastore, key); | ||
Instant endTime = Instant.now(); | ||
Duration duration = Duration.between(startTime, endTime); | ||
System.out.println("Duration: " + duration.toString()); | ||
} | ||
|
||
static void addEntity(Datastore datastore, String id) { | ||
Key key = createKey(datastore, id); | ||
Entity entity = Entity.newBuilder(key) | ||
.set("description", "hello world") | ||
.build(); | ||
datastore.add(entity); | ||
System.out.println("Successfully added entity."); | ||
} | ||
|
||
static void getEntity(Datastore datastore, String id) { | ||
Key key = createKey(datastore, id); | ||
Entity entity = datastore.get(key); | ||
System.out.println("Reading entity: " + entity.getKey().getName()); | ||
} | ||
|
||
static void deleteEntity(Datastore datastore, String id) { | ||
Key key = createKey(datastore, id); | ||
datastore.delete(key); | ||
|
||
Entity entity = datastore.get(key); | ||
if (entity == null) { | ||
System.out.println("Successfully deleted entity: " + id); | ||
} else { | ||
throw new RuntimeException("Failed to delete entity: " + id); | ||
} | ||
} | ||
|
||
static void runTransactionCallable(Datastore datastore, Key entityKey) { | ||
datastore.runInTransaction(client -> { | ||
Entity entity = Entity.newBuilder(entityKey) | ||
.set("description", "hello world") | ||
.build(); | ||
datastore.add(entity); | ||
|
||
StructuredQuery query = | ||
Query.newEntityQueryBuilder() | ||
.setNamespace(TEST_NAMESPACE) | ||
.setKind(TEST_KIND) | ||
.build(); | ||
|
||
QueryResults<Entity> results = datastore.run(query); | ||
while (results.hasNext()) { | ||
Entity result = results.next(); | ||
String name = result.getKey().getName(); | ||
String kind = result.getKey().getKind(); | ||
String namespace = result.getKey().getNamespace(); | ||
System.out.println( | ||
"Found entity:" + "\n\t\tname=" + name + "\n\t\tkind=" + kind + "\n\t\tnamespace=" | ||
+ namespace + "\n\t\tproperties=" + result.getProperties().toString()); | ||
} | ||
|
||
datastore.delete(entityKey); | ||
return null; | ||
}); | ||
|
||
System.out.println("Ran transaction callable."); | ||
} | ||
|
||
private static void runTransaction(Datastore datastore) { | ||
Transaction transaction = datastore.newTransaction(); | ||
transaction.commit(); | ||
transaction = datastore.newTransaction(); | ||
transaction.rollback(); | ||
System.out.println("Run fake transaction code."); | ||
} | ||
|
||
static Key createKey(Datastore datastore, String id) { | ||
return datastore.newKeyFactory() | ||
.setNamespace(TEST_NAMESPACE) | ||
.setKind(TEST_KIND) | ||
.newKey(id); | ||
} | ||
} |
Oops, something went wrong.