diff --git a/README.md b/README.md index 7dfbb2041f..e2ed4cb546 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,7 @@ Samples are in the [`samples/`](https://github.com/googleapis/java-storage/tree/ | Sample | Source Code | Try it | | --------------------------- | --------------------------------- | ------ | +| 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) | | 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) | | 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) | | 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) | diff --git a/samples/native-image-sample/README.md b/samples/native-image-sample/README.md new file mode 100644 index 0000000000..092cdc0591 --- /dev/null +++ b/samples/native-image-sample/README.md @@ -0,0 +1,80 @@ +# Storage Sample Application with Native Image + +The Storage sample application demonstrates some common operations with Google Cloud Storage and is compatible with Native Image compilation. + +## Setup Instructions + +You will need to follow these prerequisite steps in order to run these 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) + ``` + +4. [Enable the Cloud Storage APIs](https://console.cloud.google.com/apis/api/storage.googleapis.com). + +### Run with Native Image Compilation + +Navigate to this directory in a new terminal. + +1. Compile the application using the Native Image Compiler. This step may take a few minutes. + + ``` + mvn package -P native -DskipTests + ``` + +2. Run the application: + + ``` + ./target/native-image-sample + ``` + +3. The application will run through basic Cloud Storage operations of creating, reading, and deleting Cloud Storage resources. + + 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. + + ``` + Creating bucket nativeimage-sample-bucket-7221f161-688c-4a7a-9120-8900d20f0802 + Write file to bucket. + Reading the file that was written... + Successfully wrote to file: Hello World! + Cleaning up resources... + Deleted file nativeimage-sample-file-5d927aaf-cb03-41de-8383-696733893db5 + Deleted bucket nativeimage-sample-bucket-7221f161-688c-4a7a-9120-8900d20f0802 + ``` + +## 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 + ``` \ No newline at end of file diff --git a/samples/native-image-sample/pom.xml b/samples/native-image-sample/pom.xml new file mode 100644 index 0000000000..470ceecebc --- /dev/null +++ b/samples/native-image-sample/pom.xml @@ -0,0 +1,173 @@ + + + 4.0.0 + com.google.cloud + native-image-sample + Native Image Sample + https://github.com/googleapis/java-storage + + + + com.google.cloud.samples + shared-configuration + 1.2.0 + + + + + 1.8 + 1.8 + UTF-8 + + + + + + com.google.cloud + libraries-bom + 24.3.0 + pom + import + + + + + + + com.google.cloud + google-cloud-core + + + com.google.cloud + google-cloud-storage + + + + junit + junit + 4.13.2 + test + + + com.google.truth + truth + 1.1.3 + test + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + + + + true + dependency-jars/ + com.example.storage.NativeImageStorageSample + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-dependencies + package + + copy-dependencies + + + + ${project.build.directory}/dependency-jars/ + + + + + + + + + + + + native + + + + com.google.cloud + native-image-support + 0.12.0 + + + org.junit.vintage + junit-vintage-engine + 5.8.2 + test + + + org.graalvm.buildtools + junit-platform-native + 0.9.9 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 2.22.2 + + + **/*IT + + + + + org.graalvm.buildtools + native-maven-plugin + 0.9.9 + true + + com.example.storage.NativeImageStorageSample + + --no-fallback + --no-server + + + + + build-native + + build + test + + package + + + test-native + + test + + test + + + + + + + + \ No newline at end of file diff --git a/samples/native-image-sample/src/main/java/com/example/storage/NativeImageStorageSample.java b/samples/native-image-sample/src/main/java/com/example/storage/NativeImageStorageSample.java new file mode 100644 index 0000000000..ce4cf6b5ef --- /dev/null +++ b/samples/native-image-sample/src/main/java/com/example/storage/NativeImageStorageSample.java @@ -0,0 +1,92 @@ +/* + * Copyright 2022 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 + * + * http://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.storage; + +import com.google.cloud.BatchResult.Callback; +import com.google.cloud.storage.Blob; +import com.google.cloud.storage.BlobId; +import com.google.cloud.storage.BlobInfo; +import com.google.cloud.storage.BucketInfo; +import com.google.cloud.storage.Storage; +import com.google.cloud.storage.StorageBatch; +import com.google.cloud.storage.StorageException; +import com.google.cloud.storage.StorageOptions; +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +/** Sample Storage application compiled with Native Image. */ +public class NativeImageStorageSample { + + static String BUCKET_NAME = "nativeimage-sample-bucket-" + UUID.randomUUID(); + static String FILENAME = "nativeimage-sample-file-" + UUID.randomUUID(); + + /** Runs the storage sample application. */ + public static void main(String[] args) { + + Storage storageClient = StorageOptions.getDefaultInstance().getService(); + + try { + createBucket(storageClient, BUCKET_NAME); + createFile(storageClient, BUCKET_NAME, FILENAME); + runBatchOperations(storageClient, BUCKET_NAME, FILENAME); + } finally { + System.out.println("Deleting resources."); + storageClient.delete(BUCKET_NAME, FILENAME); + storageClient.delete(BUCKET_NAME); + } + } + + private static void runBatchOperations( + Storage storageClient, String bucketName, String fileName) { + BlobId blobId = BlobId.of(bucketName, fileName); + + StorageBatch batch = storageClient.batch(); + batch + .update(BlobInfo.newBuilder(blobId).build()) + .notify( + new Callback() { + @Override + public void success(Blob blob) { + System.out.println("Batch update succeeded on " + fileName); + } + + @Override + public void error(StorageException e) { + System.out.println("Batch update failed with cause: " + e); + } + }); + + batch.submit(); + } + + private static void createBucket(Storage storageClient, String bucketName) { + BucketInfo bucketInfo = BucketInfo.newBuilder(bucketName).setLocation("us-east1").build(); + storageClient.create(bucketInfo); + System.out.println("Created bucket " + bucketName); + } + + private static void createFile(Storage storageClient, String bucketName, String fileName) { + BlobInfo blobInfo = + BlobInfo.newBuilder(bucketName, fileName).setContentType("text/plain").build(); + storageClient.create(blobInfo, "Hello World!".getBytes(StandardCharsets.UTF_8)); + System.out.println("Created file " + blobInfo.getName()); + + Blob blob = storageClient.get(bucketName, fileName); + String content = new String(blob.getContent(), StandardCharsets.UTF_8); + System.out.println("Successfully wrote to file: " + content); + } +} diff --git a/samples/native-image-sample/src/test/java/com/example/storage/NativeImageStorageSampleIT.java b/samples/native-image-sample/src/test/java/com/example/storage/NativeImageStorageSampleIT.java new file mode 100644 index 0000000000..5098402647 --- /dev/null +++ b/samples/native-image-sample/src/test/java/com/example/storage/NativeImageStorageSampleIT.java @@ -0,0 +1,39 @@ +/* + * Copyright 2022 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 + * + * http://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.storage; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.cloud.testing.junit4.StdOutCaptureRule; +import org.junit.Rule; +import org.junit.Test; + +public class NativeImageStorageSampleIT { + + @Rule public StdOutCaptureRule stdOut = new StdOutCaptureRule(); + + @Test + public void createAndReadStorageResources() { + NativeImageStorageSample.main(new String[] {}); + assertThat(stdOut.getCapturedOutputAsUtf8String()) + .contains("Created bucket " + NativeImageStorageSample.BUCKET_NAME); + assertThat(stdOut.getCapturedOutputAsUtf8String()) + .contains("Created file " + NativeImageStorageSample.FILENAME); + assertThat(stdOut.getCapturedOutputAsUtf8String()) + .contains("Successfully wrote to file: Hello World!"); + } +} diff --git a/samples/pom.xml b/samples/pom.xml index 26e701c339..2c01e6fca0 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -31,6 +31,7 @@ install-without-bom snapshot snippets + native-image-sample