Skip to content

Commit a01fe88

Browse files
authored
docs(sample): Add sample for native image support in Firestore (#872)
* docs(sample): Add sample for native image support
1 parent 7e7b863 commit a01fe88

File tree

7 files changed

+485
-0
lines changed

7 files changed

+485
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Firestore Sample Application with Native Image
2+
3+
This application uses the [Google Cloud Firestore client libraries](https://cloud.google.com/firestore/docs/quickstart-servers#java) and is compatible with Native Image compilation.
4+
5+
This sample runs through basic operations of creating a new document, running queries, and then deleting the created resources.
6+
7+
## Setup Instructions
8+
9+
You will need to follow these prerequisite steps in order to run the 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/#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.7" 2020-04-14
40+
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
41+
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)
42+
```
43+
44+
## Sample
45+
46+
1. If you wish to run the application against the [Firestore emulator](https://cloud.google.com/sdk/gcloud/reference/beta/emulators/firestore), 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 firestore start --host-port=localhost:9010
52+
```
53+
54+
Leave the emulator running in this terminal for now.
55+
In the next section, we will run the sample application against the Firestore emulator instance.
56+
57+
58+
2. Navigate to this directory and compile the application with the Native Image compiler.
59+
60+
```
61+
mvn package -P native -DskipTests
62+
```
63+
64+
3. **(Optional)** If you're using the emulator, export the `FIRESTORE_EMULATOR_HOST` as an environment variable in your terminal.
65+
66+
```
67+
export FIRESTORE_EMULATOR_HOST=localhost:9010
68+
```
69+
70+
The Firestore Client Libraries will detect this environment variable and automatically connect to the emulator instance if this variable is set.
71+
72+
4. Run the application.
73+
74+
```
75+
./target/native-image-sample
76+
```
77+
78+
5. The application will run through some basic Firestore operations and log some output statements.
79+
80+
```
81+
Created user alovelace. Timestamp: 2020-12-15T20:19:28.444070000Z
82+
The following users were saved:
83+
Document: alovelace | Ada Lovelace born 1815
84+
Number of users born before 1900: 1
85+
Number of users born earlier after 1900: 0
86+
Number of users whose first name is 'Ada': 0
87+
```
88+
89+
## Sample Integration test with Native Image Support
90+
91+
In order to run the sample integration test as a native image, call the following command:
92+
93+
```
94+
mvn test -Pnative
95+
```
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<?xml version='1.0' encoding='UTF-8'?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
<groupId>com.example.firestore</groupId>
8+
<artifactId>native-image-sample</artifactId>
9+
<name>Native Image Sample</name>
10+
<url>https://github.com/googleapis/java-firestore</url>
11+
12+
<!--
13+
The parent pom defines common style checks and testing strategies for our samples.
14+
Removing or replacing it should not affect the execution of the samples in anyway.
15+
-->
16+
<parent>
17+
<groupId>com.google.cloud.samples</groupId>
18+
<artifactId>shared-configuration</artifactId>
19+
<version>1.2.0</version>
20+
</parent>
21+
22+
<properties>
23+
<maven.compiler.target>11</maven.compiler.target>
24+
<maven.compiler.source>11</maven.compiler.source>
25+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
26+
</properties>
27+
28+
<dependencyManagement>
29+
<dependencies>
30+
<dependency>
31+
<groupId>com.google.cloud</groupId>
32+
<artifactId>libraries-bom</artifactId>
33+
<version>24.2.0</version>
34+
<type>pom</type>
35+
<scope>import</scope>
36+
</dependency>
37+
</dependencies>
38+
</dependencyManagement>
39+
40+
<dependencies>
41+
<dependency>
42+
<groupId>com.google.cloud</groupId>
43+
<artifactId>google-cloud-firestore</artifactId>
44+
</dependency>
45+
46+
<dependency>
47+
<groupId>junit</groupId>
48+
<artifactId>junit</artifactId>
49+
<version>4.13.2</version>
50+
<scope>test</scope>
51+
</dependency>
52+
<dependency>
53+
<groupId>com.google.truth</groupId>
54+
<artifactId>truth</artifactId>
55+
<version>1.1.3</version>
56+
<scope>test</scope>
57+
</dependency>
58+
</dependencies>
59+
60+
<build>
61+
<plugins>
62+
<plugin>
63+
<groupId>org.apache.maven.plugins</groupId>
64+
<artifactId>maven-jar-plugin</artifactId>
65+
<configuration>
66+
<archive>
67+
<manifest>
68+
<mainClass>com.example.firestore.NativeImageFirestoreSample
69+
</mainClass>
70+
</manifest>
71+
</archive>
72+
</configuration>
73+
</plugin>
74+
</plugins>
75+
</build>
76+
77+
<!-- Native Profile-->
78+
<profiles>
79+
<profile>
80+
<id>native</id>
81+
82+
<dependencies>
83+
<dependency>
84+
<groupId>com.google.cloud</groupId>
85+
<artifactId>native-image-support</artifactId>
86+
<version>0.10.0</version>
87+
</dependency>
88+
<dependency>
89+
<groupId>org.junit.vintage</groupId>
90+
<artifactId>junit-vintage-engine</artifactId>
91+
<version>5.8.2</version>
92+
<scope>test</scope>
93+
</dependency>
94+
<dependency>
95+
<groupId>org.graalvm.buildtools</groupId>
96+
<artifactId>junit-platform-native</artifactId>
97+
<version>0.9.9</version>
98+
<scope>test</scope>
99+
</dependency>
100+
</dependencies>
101+
102+
<build>
103+
<plugins>
104+
<plugin>
105+
<groupId>org.apache.maven.plugins</groupId>
106+
<artifactId>maven-surefire-plugin
107+
</artifactId> <!-- Must use older version of surefire plugin for native-image testing. -->
108+
<version>2.22.2</version>
109+
<configuration>
110+
<includes>
111+
<include>**/IT*</include>
112+
</includes>
113+
</configuration>
114+
</plugin>
115+
<plugin>
116+
<groupId>org.graalvm.buildtools</groupId>
117+
<artifactId>native-maven-plugin</artifactId>
118+
<version>0.9.9</version>
119+
<extensions>true</extensions>
120+
<configuration>
121+
<mainClass>com.example.firestore.NativeImageFirestoreSample
122+
</mainClass>
123+
<buildArgs>
124+
<buildArg>--no-fallback</buildArg>
125+
<buildArg>--no-server</buildArg>
126+
</buildArgs>
127+
</configuration>
128+
<executions>
129+
<execution>
130+
<id>build-native</id>
131+
<goals>
132+
<goal>build</goal>
133+
<goal>test</goal>
134+
</goals>
135+
<phase>package</phase>
136+
</execution>
137+
<execution>
138+
<id>test-native</id>
139+
<goals>
140+
<goal>test</goal>
141+
</goals>
142+
<phase>test</phase>
143+
</execution>
144+
</executions>
145+
</plugin>
146+
</plugins>
147+
</build>
148+
</profile>
149+
</profiles>
150+
</project>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright 2020-2021 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+
* https://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.firestore;
18+
19+
import com.google.api.core.ApiFuture;
20+
import com.google.cloud.firestore.CollectionReference;
21+
import com.google.cloud.firestore.DocumentReference;
22+
import com.google.cloud.firestore.FieldPath;
23+
import com.google.cloud.firestore.Firestore;
24+
import com.google.cloud.firestore.FirestoreOptions;
25+
import com.google.cloud.firestore.Query;
26+
import com.google.cloud.firestore.QueryDocumentSnapshot;
27+
import com.google.cloud.firestore.QuerySnapshot;
28+
import com.google.cloud.firestore.WriteResult;
29+
import java.time.Duration;
30+
import java.time.Instant;
31+
import java.util.HashMap;
32+
import java.util.List;
33+
import java.util.Map;
34+
35+
/**
36+
* Sample Firestore application demonstrating basic operations.
37+
*/
38+
public class NativeImageFirestoreSample {
39+
40+
private static final String USERS_COLLECTION = "nativeimage_test_users";
41+
42+
/**
43+
* Entrypoint to the Firestore sample application.
44+
*/
45+
public static void main(String[] args) throws Exception {
46+
Instant startTime = Instant.now();
47+
FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance();
48+
Firestore db = firestoreOptions.getService();
49+
50+
deleteCollection(db);
51+
createUserDocument(db);
52+
createUserDocumentPojo(db);
53+
readDocuments(db);
54+
runSampleQueries(db);
55+
Instant endTime = Instant.now();
56+
Duration duration = Duration.between(startTime, endTime);
57+
System.out.println("Duration: " + duration.toString());
58+
}
59+
60+
static void deleteCollection(Firestore db) throws Exception {
61+
Iterable<DocumentReference> documents = db.collection(USERS_COLLECTION).listDocuments();
62+
for (DocumentReference doc : documents) {
63+
doc.delete().get();
64+
}
65+
}
66+
67+
static void createUserDocument(Firestore db) throws Exception {
68+
DocumentReference docRef = db.collection(USERS_COLLECTION).document("alovelace");
69+
Map<String, Object> data = new HashMap<>();
70+
data.put("id", "10");
71+
data.put("first", "Ada");
72+
data.put("last", "Lovelace");
73+
data.put("born", 1815);
74+
75+
WriteResult result = docRef.set(data).get();
76+
System.out.println("Created user " + docRef.getId() + ". Timestamp: " + result.getUpdateTime());
77+
}
78+
79+
static void createUserDocumentPojo(Firestore db) throws Exception {
80+
CollectionReference collectionReference = db.collection(USERS_COLLECTION);
81+
WriteResult result =
82+
collectionReference.document()
83+
.set(new Person("Alan", "Turing", 1912))
84+
.get();
85+
86+
System.out.println("Created user by POJO. Timestamp: " + result.getUpdateTime());
87+
}
88+
89+
static void readDocuments(Firestore db) throws Exception {
90+
ApiFuture<QuerySnapshot> query = db.collection(USERS_COLLECTION).get();
91+
QuerySnapshot querySnapshot = query.get();
92+
List<QueryDocumentSnapshot> documents = querySnapshot.getDocuments();
93+
System.out.println("The following users were saved:");
94+
printUsers(documents);
95+
}
96+
97+
static void runSampleQueries(Firestore db) throws Exception {
98+
List<QueryDocumentSnapshot> results =
99+
runQuery(db.collection(USERS_COLLECTION).whereLessThan("born", 1900));
100+
System.out.println("Number of users born before 1900: " + results.size());
101+
102+
results = runQuery(
103+
db.collection(USERS_COLLECTION).whereGreaterThan(FieldPath.of("born"), 1900));
104+
System.out.println("Number of users born earlier after 1900: " + results.size());
105+
106+
results = runQuery(
107+
db.collection(USERS_COLLECTION).whereEqualTo("name", "Ada"));
108+
System.out.println("Number of users whose first name is 'Ada': " + results.size());
109+
}
110+
111+
private static List<QueryDocumentSnapshot> runQuery(Query query) throws Exception {
112+
QuerySnapshot querySnapshot = query.get().get();
113+
List<QueryDocumentSnapshot> documents = querySnapshot.getDocuments();
114+
return documents;
115+
}
116+
117+
private static void printUsers(Iterable<QueryDocumentSnapshot> documents) {
118+
for (QueryDocumentSnapshot document : documents) {
119+
System.out.printf(
120+
"Document: %s | %s %s born %d\n",
121+
document.getId(),
122+
document.getString("first"),
123+
document.getString("last"),
124+
document.getLong("born"));
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)