Skip to content

Commit 375874d

Browse files
authored
docs(sample): Add Native Image sample for Storage (#1283)
* docs(sample): Add Native Image Sample
1 parent a45feb9 commit 375874d

File tree

6 files changed

+386
-0
lines changed

6 files changed

+386
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/
227227

228228
| Sample | Source Code | Try it |
229229
| --------------------------- | --------------------------------- | ------ |
230+
| Native Image Storage Sample | [source code](https://github.com/googleapis/java-storage/blob/main/samples/native-image-sample/src/main/java/com/example/storage/NativeImageStorageSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/native-image-sample/src/main/java/com/example/storage/NativeImageStorageSample.java) |
230231
| Configure Retries | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/ConfigureRetries.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/ConfigureRetries.java) |
231232
| Quickstart Sample | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/QuickstartSample.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/QuickstartSample.java) |
232233
| Add Bucket Default Owner | [source code](https://github.com/googleapis/java-storage/blob/main/samples/snippets/src/main/java/com/example/storage/bucket/AddBucketDefaultOwner.java) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/java-storage&page=editor&open_in_editor=samples/snippets/src/main/java/com/example/storage/bucket/AddBucketDefaultOwner.java) |
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Storage Sample Application with Native Image
2+
3+
The Storage sample application demonstrates some common operations with Google Cloud Storage and is compatible with Native Image compilation.
4+
5+
## Setup Instructions
6+
7+
You will need to follow these prerequisite steps in order to run these samples:
8+
9+
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).
10+
11+
2. Install the [Google Cloud SDK](https://cloud.google.com/sdk/) which will allow you to run the sample with your project's credentials.
12+
13+
Once installed, log in with Application Default Credentials using the following command:
14+
15+
```
16+
gcloud auth application-default login
17+
```
18+
19+
**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.
20+
21+
3. Install the GraalVM compiler.
22+
23+
You can follow the [official installation instructions](https://www.graalvm.org/docs/getting-started/#install-graalvm) from the GraalVM website.
24+
After following the instructions, ensure that you install the Native Image extension installed by running:
25+
26+
```
27+
gu install native-image
28+
```
29+
30+
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.
31+
32+
You will see something similar to the below output:
33+
34+
```
35+
$ java -version
36+
37+
openjdk version "11.0.7" 2020-04-14
38+
OpenJDK Runtime Environment GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02)
39+
OpenJDK 64-Bit Server VM GraalVM CE 20.1.0 (build 11.0.7+10-jvmci-20.1-b02, mixed mode, sharing)
40+
```
41+
42+
4. [Enable the Cloud Storage APIs](https://console.cloud.google.com/apis/api/storage.googleapis.com).
43+
44+
### Run with Native Image Compilation
45+
46+
Navigate to this directory in a new terminal.
47+
48+
1. Compile the application using the Native Image Compiler. This step may take a few minutes.
49+
50+
```
51+
mvn package -P native -DskipTests
52+
```
53+
54+
2. Run the application:
55+
56+
```
57+
./target/native-image-sample
58+
```
59+
60+
3. The application will run through basic Cloud Storage operations of creating, reading, and deleting Cloud Storage resources.
61+
62+
You can manually manage Cloud Storage resources through [Google Cloud Console](https://console.cloud.google.com/storage) to verify that the resources are cleaned up.
63+
64+
```
65+
Creating bucket nativeimage-sample-bucket-7221f161-688c-4a7a-9120-8900d20f0802
66+
Write file to bucket.
67+
Reading the file that was written...
68+
Successfully wrote to file: Hello World!
69+
Cleaning up resources...
70+
Deleted file nativeimage-sample-file-5d927aaf-cb03-41de-8383-696733893db5
71+
Deleted bucket nativeimage-sample-bucket-7221f161-688c-4a7a-9120-8900d20f0802
72+
```
73+
74+
## Sample Integration test with Native Image Support
75+
76+
In order to run the sample integration test as a native image, call the following command:
77+
78+
```
79+
mvn test -Pnative
80+
```
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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-sample</artifactId>
6+
<name>Native Image Sample</name>
7+
<url>https://github.com/googleapis/java-storage</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>24.3.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-core</artifactId>
42+
</dependency>
43+
<dependency>
44+
<groupId>com.google.cloud</groupId>
45+
<artifactId>google-cloud-storage</artifactId>
46+
</dependency>
47+
48+
<dependency>
49+
<groupId>junit</groupId>
50+
<artifactId>junit</artifactId>
51+
<version>4.13.2</version>
52+
<scope>test</scope>
53+
</dependency>
54+
<dependency>
55+
<groupId>com.google.truth</groupId>
56+
<artifactId>truth</artifactId>
57+
<version>1.1.3</version>
58+
<scope>test</scope>
59+
</dependency>
60+
</dependencies>
61+
62+
<build>
63+
<!-- This plugin enables building the application to a JAR *not* using Native Image -->
64+
<plugins>
65+
<plugin>
66+
<groupId>org.apache.maven.plugins</groupId>
67+
<artifactId>maven-jar-plugin</artifactId>
68+
<version>3.2.2</version>
69+
<configuration>
70+
<archive>
71+
<manifest>
72+
<addClasspath>true</addClasspath>
73+
<classpathPrefix>dependency-jars/</classpathPrefix>
74+
<mainClass>com.example.storage.NativeImageStorageSample</mainClass>
75+
</manifest>
76+
</archive>
77+
</configuration>
78+
</plugin>
79+
<plugin>
80+
<groupId>org.apache.maven.plugins</groupId>
81+
<artifactId>maven-dependency-plugin</artifactId>
82+
<version>3.2.0</version>
83+
<executions>
84+
<execution>
85+
<id>copy-dependencies</id>
86+
<phase>package</phase>
87+
<goals>
88+
<goal>copy-dependencies</goal>
89+
</goals>
90+
<configuration>
91+
<outputDirectory>
92+
${project.build.directory}/dependency-jars/
93+
</outputDirectory>
94+
</configuration>
95+
</execution>
96+
</executions>
97+
</plugin>
98+
</plugins>
99+
</build>
100+
101+
<!-- Native Profile-->
102+
<profiles>
103+
<profile>
104+
<id>native</id>
105+
106+
<dependencies>
107+
<dependency>
108+
<groupId>com.google.cloud</groupId>
109+
<artifactId>native-image-support</artifactId>
110+
<version>0.12.0</version>
111+
</dependency>
112+
<dependency>
113+
<groupId>org.junit.vintage</groupId>
114+
<artifactId>junit-vintage-engine</artifactId>
115+
<version>5.8.2</version>
116+
<scope>test</scope>
117+
</dependency>
118+
<dependency>
119+
<groupId>org.graalvm.buildtools</groupId>
120+
<artifactId>junit-platform-native</artifactId>
121+
<version>0.9.9</version>
122+
<scope>test</scope>
123+
</dependency>
124+
</dependencies>
125+
126+
<build>
127+
<plugins>
128+
<plugin>
129+
<groupId>org.apache.maven.plugins</groupId>
130+
<artifactId>maven-surefire-plugin
131+
</artifactId> <!-- Must use older version of surefire plugin for native-image testing. -->
132+
<version>2.22.2</version>
133+
<configuration>
134+
<includes>
135+
<include>**/*IT</include>
136+
</includes>
137+
</configuration>
138+
</plugin>
139+
<plugin>
140+
<groupId>org.graalvm.buildtools</groupId>
141+
<artifactId>native-maven-plugin</artifactId>
142+
<version>0.9.9</version>
143+
<extensions>true</extensions>
144+
<configuration>
145+
<mainClass>com.example.storage.NativeImageStorageSample</mainClass>
146+
<buildArgs>
147+
<buildArg>--no-fallback</buildArg>
148+
<buildArg>--no-server</buildArg>
149+
</buildArgs>
150+
</configuration>
151+
<executions>
152+
<execution>
153+
<id>build-native</id>
154+
<goals>
155+
<goal>build</goal>
156+
<goal>test</goal>
157+
</goals>
158+
<phase>package</phase>
159+
</execution>
160+
<execution>
161+
<id>test-native</id>
162+
<goals>
163+
<goal>test</goal>
164+
</goals>
165+
<phase>test</phase>
166+
</execution>
167+
</executions>
168+
</plugin>
169+
</plugins>
170+
</build>
171+
</profile>
172+
</profiles>
173+
</project>
Lines changed: 92 additions & 0 deletions
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.storage;
18+
19+
import com.google.cloud.BatchResult.Callback;
20+
import com.google.cloud.storage.Blob;
21+
import com.google.cloud.storage.BlobId;
22+
import com.google.cloud.storage.BlobInfo;
23+
import com.google.cloud.storage.BucketInfo;
24+
import com.google.cloud.storage.Storage;
25+
import com.google.cloud.storage.StorageBatch;
26+
import com.google.cloud.storage.StorageException;
27+
import com.google.cloud.storage.StorageOptions;
28+
import java.nio.charset.StandardCharsets;
29+
import java.util.UUID;
30+
31+
/** Sample Storage application compiled with Native Image. */
32+
public class NativeImageStorageSample {
33+
34+
static String BUCKET_NAME = "nativeimage-sample-bucket-" + UUID.randomUUID();
35+
static String FILENAME = "nativeimage-sample-file-" + UUID.randomUUID();
36+
37+
/** Runs the storage sample application. */
38+
public static void main(String[] args) {
39+
40+
Storage storageClient = StorageOptions.getDefaultInstance().getService();
41+
42+
try {
43+
createBucket(storageClient, BUCKET_NAME);
44+
createFile(storageClient, BUCKET_NAME, FILENAME);
45+
runBatchOperations(storageClient, BUCKET_NAME, FILENAME);
46+
} finally {
47+
System.out.println("Deleting resources.");
48+
storageClient.delete(BUCKET_NAME, FILENAME);
49+
storageClient.delete(BUCKET_NAME);
50+
}
51+
}
52+
53+
private static void runBatchOperations(
54+
Storage storageClient, String bucketName, String fileName) {
55+
BlobId blobId = BlobId.of(bucketName, fileName);
56+
57+
StorageBatch batch = storageClient.batch();
58+
batch
59+
.update(BlobInfo.newBuilder(blobId).build())
60+
.notify(
61+
new Callback<Blob, StorageException>() {
62+
@Override
63+
public void success(Blob blob) {
64+
System.out.println("Batch update succeeded on " + fileName);
65+
}
66+
67+
@Override
68+
public void error(StorageException e) {
69+
System.out.println("Batch update failed with cause: " + e);
70+
}
71+
});
72+
73+
batch.submit();
74+
}
75+
76+
private static void createBucket(Storage storageClient, String bucketName) {
77+
BucketInfo bucketInfo = BucketInfo.newBuilder(bucketName).setLocation("us-east1").build();
78+
storageClient.create(bucketInfo);
79+
System.out.println("Created bucket " + bucketName);
80+
}
81+
82+
private static void createFile(Storage storageClient, String bucketName, String fileName) {
83+
BlobInfo blobInfo =
84+
BlobInfo.newBuilder(bucketName, fileName).setContentType("text/plain").build();
85+
storageClient.create(blobInfo, "Hello World!".getBytes(StandardCharsets.UTF_8));
86+
System.out.println("Created file " + blobInfo.getName());
87+
88+
Blob blob = storageClient.get(bucketName, fileName);
89+
String content = new String(blob.getContent(), StandardCharsets.UTF_8);
90+
System.out.println("Successfully wrote to file: " + content);
91+
}
92+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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.storage;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
21+
import com.google.cloud.testing.junit4.StdOutCaptureRule;
22+
import org.junit.Rule;
23+
import org.junit.Test;
24+
25+
public class NativeImageStorageSampleIT {
26+
27+
@Rule public StdOutCaptureRule stdOut = new StdOutCaptureRule();
28+
29+
@Test
30+
public void createAndReadStorageResources() {
31+
NativeImageStorageSample.main(new String[] {});
32+
assertThat(stdOut.getCapturedOutputAsUtf8String())
33+
.contains("Created bucket " + NativeImageStorageSample.BUCKET_NAME);
34+
assertThat(stdOut.getCapturedOutputAsUtf8String())
35+
.contains("Created file " + NativeImageStorageSample.FILENAME);
36+
assertThat(stdOut.getCapturedOutputAsUtf8String())
37+
.contains("Successfully wrote to file: Hello World!");
38+
}
39+
}

0 commit comments

Comments
 (0)