diff --git a/.kokoro/java11/presubmit.cfg b/.kokoro/java11/presubmit.cfg index cac8b604bd2..5f395247e51 100644 --- a/.kokoro/java11/presubmit.cfg +++ b/.kokoro/java11/presubmit.cfg @@ -17,5 +17,5 @@ # Tell the trampoline which build file to use. env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-docs-samples/.kokoro/tests/diff_tests.sh" + value: "github/java-docs-samples/.kokoro/tests/run_diff_only.sh" } diff --git a/.kokoro/java8/presubmit.cfg b/.kokoro/java8/presubmit.cfg index cac8b604bd2..5f395247e51 100644 --- a/.kokoro/java8/presubmit.cfg +++ b/.kokoro/java8/presubmit.cfg @@ -17,5 +17,5 @@ # Tell the trampoline which build file to use. env_vars: { key: "TRAMPOLINE_BUILD_FILE" - value: "github/java-docs-samples/.kokoro/tests/diff_tests.sh" + value: "github/java-docs-samples/.kokoro/tests/run_diff_only.sh" } diff --git a/.kokoro/tests/diff_tests.sh b/.kokoro/tests/diff_tests.sh deleted file mode 100755 index 45ee00b0915..00000000000 --- a/.kokoro/tests/diff_tests.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# Copyright 2017 Google Inc. -# -# 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. - -set -e -o pipefail -shopt -s globstar -# We spin up some subprocesses. Don't kill them on hangup -trap '' HUP - -# Update gcloud and check version -gcloud components update --quiet -echo -e "\n ********** GCLOUD INFO *********** \n" -gcloud -v -echo -e "\n ********** MAVEN INFO *********** \n" -mvn -v -echo -e "\n ********** GRADLE INFO *********** " -gradle -v - -# Setup required environmental variables -export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-acct.json -export GOOGLE_CLOUD_PROJECT=java-docs-samples-testing -source ${KOKORO_GFILE_DIR}/aws-secrets.sh -source ${KOKORO_GFILE_DIR}/storage-hmac-credentials.sh -source ${KOKORO_GFILE_DIR}/dlp_secrets.txt -# Activate service account -gcloud auth activate-service-account\ - --key-file=$GOOGLE_APPLICATION_CREDENTIALS \ - --project=$GOOGLE_CLOUD_PROJECT - -echo -e "\n******************** TESTING AFFECTED PROJECTS ********************" -set +e -# Diff to find out what has changed from master -RESULT=0 -cd github/java-docs-samples -# For every pom.xml (may break on whitespace) -for file in **/pom.xml; do - # Navigate to project - file=$(dirname "$file") - pushd "$file" > /dev/null - - # Only tests changed projects - git diff --quiet master.. . - CHANGED=$? - - # Only test leafs to prevent testing twice - PARENT=$(grep "" pom.xml -c) - - # Get the Java version from the pom.xml - VERSION=$(grep -oP '(?<=).*?(?=)' pom.xml) - - # Check for changes to the current folder - if [ "$CHANGED" -eq 1 ] && [ "$PARENT" -eq 0 ] && [[ "$JAVA_VERSION" = *"$VERSION"* ]]; then - echo "------------------------------------------------------------" - echo "- testing $file" - echo "------------------------------------------------------------" - - # Run tests and update RESULT if failed - mvn -q --batch-mode --fail-at-end clean verify \ - -Dfile.encoding="UTF-8" \ - -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ - -Dmaven.test.redirectTestOutputToFile=true \ - -Dbigtable.projectID="${GOOGLE_CLOUD_PROJECT}" \ - -Dbigtable.instanceID=instance - EXIT=$? - - if [ $EXIT -ne 0 ]; then - echo -e "\n Tests failed. \n" - RESULT=1 - else - echo -e "\n Tests complete. \n" - fi - fi - - popd > /dev/null - -done - -exit $RESULT diff --git a/.kokoro/tests/run_diff_only.sh b/.kokoro/tests/run_diff_only.sh new file mode 100755 index 00000000000..456f442b789 --- /dev/null +++ b/.kokoro/tests/run_diff_only.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# +# 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. +mydir="${0%/*}" +"$mydir"/run_tests.sh --only-diff \ No newline at end of file diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh index dcebd8380a4..8ef7495ac24 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -13,72 +13,126 @@ # See the License for the specific language governing permissions and # limitations under the License. +# `-e` enables the script to automatically fail when a command fails +# `-o pipefail` sets the exit code to the rightmost comment to exit with a non-zero set -eo pipefail +# Enables `**` to include files nested inside sub-folders shopt -s globstar -# We spin up some subprocesses. Don't kill them on hangup -trap '' HUP - -# Update gcloud and check version -gcloud components update --quiet -echo "********** GCLOUD INFO ***********" -gcloud -v -echo "********** MAVEN INFO ***********" -mvn -v -echo "********** GRADLE INFO ***********" -gradle -v - -# Setup required enviormental variables -export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-acct.json -export GOOGLE_CLOUD_PROJECT=java-docs-samples-testing -source ${KOKORO_GFILE_DIR}/aws-secrets.sh -source ${KOKORO_GFILE_DIR}/storage-hmac-credentials.sh -source ${KOKORO_GFILE_DIR}/dlp_secrets.txt -# Activate service account -gcloud auth activate-service-account\ - --key-file=$GOOGLE_APPLICATION_CREDENTIALS \ - --project=$GOOGLE_CLOUD_PROJECT - -echo -e "\n******************** TESTING AFFECTED PROJECTS ********************" + +# `--debug` can be added make local testing of this script easier +if [[ $* == *--script-debug* ]]; then + SCRIPT_DEBUG="true" + JAVA_VERSION="1.8" +else + SCRIPT_DEBUG="false" +fi + +# `--only-changed` will only run tests on projects container changes from the master branch. +if [[ $* == *--only-diff* ]]; then + ONLY_DIFF="true" +else + ONLY_DIFF="false" +fi + +# Verify Java versions have been specified +if [[ -z ${JAVA_VERSION+x} ]]; then + echo -e "'JAVA_VERSION' env var should be a comma delimited list of valid java versions." + exit 1 +fi + +if [[ "$SCRIPT_DEBUG" != "true" ]]; then + # Update `gcloud` and log versioning for debugging. + gcloud components update --quiet + echo "********** GCLOUD INFO ***********" + gcloud -v + echo "********** MAVEN INFO ***********" + mvn -v + echo "********** GRADLE INFO ***********" + gradle -v + + # Setup required env variables + export GOOGLE_CLOUD_PROJECT=java-docs-samples-testing + export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-acct.json + source "${KOKORO_GFILE_DIR}/aws-secrets.sh" + source "${KOKORO_GFILE_DIR}/storage-hmac-credentials.sh" + source "${KOKORO_GFILE_DIR}/dlp_secrets.txt" + source "${KOKORO_GFILE_DIR}/bigtable_secrets.txt" + # Activate service account + gcloud auth activate-service-account \ + --key-file="$GOOGLE_APPLICATION_CREDENTIALS" \ + --project="$GOOGLE_CLOUD_PROJECT" + + cd github/java-docs-samples +fi + +# Package local jetty dependency for Java11 samples +if [[ "$JAVA_VERSION" == "11" ]]; then + cd appengine-java11/appengine-simple-jetty-main/ + mvn install + cd ../../ +fi + +echo -e "\n******************** TESTING PROJECTS ********************" +# Switch to 'fail at end' to allow all tests to complete before exiting. set +e -RESULT=0 -cd github/java-docs-samples -# For every pom.xml (may break on whitespace) +# Use RTN to return a non-zero value if the test fails. +RTN=0 +ROOT=$(pwd) +# Find all POMs in the repository (may break on whitespace). for file in **/pom.xml; do - # Navigate to project + cd "$ROOT" + # Navigate to the project folder. file=$(dirname "$file") - pushd "$file" > /dev/null - - # Only test leafs to prevent testing twice - PARENT=$(grep "" pom.xml -c) - - # Get the Java version from the pom.xml - VERSION=$(grep -oP '(?<=).*?(?=)' pom.xml) - - # Check for changes to the current folder - if [ "$PARENT" -eq 0 ] && [[ "$JAVA_VERSION" = *"$VERSION"* ]]; then - echo "------------------------------------------------------------" - echo "- testing $file" - echo "------------------------------------------------------------" - - # Run tests and update RESULT if failed - mvn -q --batch-mode --fail-at-end clean verify \ - -Dfile.encoding="UTF-8" \ - -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ - -Dmaven.test.redirectTestOutputToFile=true \ - -Dbigtable.projectID="${GOOGLE_CLOUD_PROJECT}" \ - -Dbigtable.instanceID=instance - EXIT=$? - - if [ $EXIT -ne 0 ]; then - echo -e "\n Tests failed. \n" - RESULT=1 - else - echo -e "\n Tests complete. \n" + cd "$file" + + # If $DIFF_ONLY is true, skip projects without changes. + if [[ "$ONLY_DIFF" = "true" ]]; then + git diff --quiet origin/master.. . + CHANGED=$? + if [[ "$CHANGED" -eq 0 ]]; then + # echo -e "\n Skipping $file: no changes in folder.\n" + continue fi fi - popd > /dev/null + echo "------------------------------------------------------------" + echo "- testing $file" + echo "------------------------------------------------------------" + + # Fail the tests if no Java version was found. + POM_JAVA=$(grep -oP '(?<=).*?(?=)' pom.xml) + if [[ "$POM_JAVA" = "" ]]; then + RTN=1 + echo -e "\n Testing failed: Unable to determine Java version. Please set in pom:" + echo -e "\n" + echo -e " 1.8" + echo -e " 1.8" + echo -e "\n" + continue + fi + + # Skip tests that don't have the correct Java version. + if ! [[ ",$JAVA_VERSION," =~ ",$POM_JAVA," ]]; then + echo -e "\n Skipping tests: Java version ($POM_JAVA) not required ($JAVA_VERSION)\n" + continue + fi + + # Use maven to execute the tests for the project. + mvn -q --batch-mode --fail-at-end clean verify \ + -Dfile.encoding="UTF-8" \ + -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \ + -Dmaven.test.redirectTestOutputToFile=true \ + -Dbigtable.projectID="${GOOGLE_CLOUD_PROJECT}" \ + -Dbigtable.instanceID=instance + EXIT=$? + + if [[ $EXIT -ne 0 ]]; then + RTN=1 + echo -e "\n Testing failed: Maven returned a non-zero exit code. \n" + else + echo -e "\n Testing completed.\n" + fi done -exit $RESULT +exit "$RTN" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24ba9a4cd70..a677279e590 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,13 +40,7 @@ accept your pull requests. ## Contributing a new sample -1. App Engine Standard samples all go into `/appengine` (java 7) or `/java8-appengine` (Java 8) (if you're contributing a group of samples, -please put the App Engine Standard sample into `/appengine` and provide a link in both `README.md`'s for -the project for the additional sample. - -1. App Engine Flexible samples all go into `/flexible` - -1. Technology samples go into the project root. +1. See the [SAMPLE_FORMAT.md](SAMPLE_FORMAT.md) for guidelines on the preferred sample format. ## Build Tools diff --git a/README.md b/README.md index 3f7fbcc9419..6d08e3e677f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ This is a repository that contains java code snippets on [Cloud Platform Documen Technology Samples: * [Bigquery](bigquery) +* [Data Catalog](datacatalog) * [Datastore](datastore) * [Endpoints](endpoints) * [Identity-Aware Proxy](iap) diff --git a/SAMPLE_FORMAT.md b/SAMPLE_FORMAT.md new file mode 100644 index 00000000000..8b1492da847 --- /dev/null +++ b/SAMPLE_FORMAT.md @@ -0,0 +1,132 @@ +# Samples Format + +This doc maintains an outline for 'snippet' samples specific to Java. Currently, the java canonical +samples in this format are located +[here](https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/dlp/src/main/java/dlp/snippets). + + +## Specific Goals +This sample format is intended to help enforce some specific goals in our samples. Even if not +specifically mentioned in the format, samples should make best-effort attempts in the following: + +* __Easily runnable__ - samples should be as easy for a user to run as possible. Users should be + able to copy and paste the code into their own environments and run with as few and transparent + modifications as possible. + +* __Teach through code__ - samples should teach users how and why specific best practices should + be implemented and performed when interacting with our services. + +* __Idiomatic__ - examples should make best attempts to remain idiomatic and encourage good + practices that are specific to a language or practice. + +## Format Guidelines + +### Project Location +Samples should be in a project folder under the name of the product the snippet represents. + Additional sub folders should be used to differentiate groups of samples. Folder and package paths + should try to avoid containing unnecessary folders to allow users to more easily navigate to the + snippets themselves. + +### Project Dependencies +Project should have a `pom.xml` that is readably formatted, declares a parent pom as shown below, + and declares all dependencies needed for the project. Best attempts should be made to minimize + necessary dependencies without sacrificing the idiomatic practices. + +```xml + + + com.google.cloud.samples + shared-configuration + SPECIFY_LATEST_VERSION + +``` + +### Project Setup +The README.md should contain instructions for the user to get the samples operable. Ideally, steps + such as project or resource setup should be links to Cloud Documentation. This is to reduce + duplicate instructions and README maintenance in the future. + +### Sample Structure +Each snippet should be be contained in its own file, within a class with a name descriptive of + the snippet and a similarly named function. Region tags should start below the package, but should + include the class and any imports in full. Additional functions can be used if it improves + readability of the sample. + +### Function Parameters +Function parameters should be limited to what is absolutely required for testing. For example, + project specific information (such as `projectId`) or a `filePath` for an external file are + allowed. A parameter for the type of a file or a specific action is not. + +Any declared function parameters should include a commented out example of how that parameter could + be declared. This provides both an example of how to derive the variables and what information they + should represent. + +### Function Return Type +The function in the snippet should not return any value. Instead, they should print the results of + actions to the console to be validated later. + +### Exception Handling +The snippet should show how to correctly handle Exceptions that occur during the snippet. Top level + exceptions can be handled by logging the exception to `System.out.println`. If the exception is + something the user may commonly encounter, include a comment explaining how to avoid or handle + correctly. + +Example: +```java +try { + // Do something +} catch (IllegalArgumentException e) { + // IllegalArgumentException's are thrown when an invalid argument has been passed to a function. + // This error should be logged to that the root cause can be debugged and prevented in the future. + System.out.println("Error during functionName: \n" + e.toString()); +} +``` + +### Client Initialization +The preferred style for initialization is to use a try-with-resources statement with a comment +clarifying how to handle multiple requests and clean up instructions. + +Example: +```java +// Initialize client that will be used to send requests. This client only needs to be created +// once, and can be reused for multiple requests. After completing all of your requests, call +// the "close" method on the client to safely clean up any remaining background resources. +try (DlpServiceClient dlp = DlpServiceClient.create()) { + // Do something +} catch (Exception e) { + System.out.println("Error during functionName: \n" + e.toString()); +} +``` + +### Arrange, Act, Assert +Samples should generally follow the following outline: +* _Arrange_ - Create and configure the components for the request. Avoid nesting these components, + as often they use Builders which can hinder readibility. +* _Act_ - Send the request and receive the response. +* _Assert_ - Verify the call was successful or that the response is correct. This is often done by + print contents of the response to stdout. + +### Testing +Snippets should have tests that should verify the snippet works and compiles correctly. Creating + mocks for these tests are optional. These tests should capture output created by the snippet to + verify that it works correctly. See the tests in the cannoncial for an example of how to do this + correctly. + +### External Resources +Use of environment variables over system properties is strongly preferred for configuration. + +Any additional files required should be stored in `src/test/resources`. + +## Additional Best Practices + +The following are some general Java best practices that should be followed in samples to remain +idiomatic. + +### Time +Use the `java.time` package when dealing with units of time in some manner. + +### Logging +Use `java.util.logging` for consistent logging in web applications. \ No newline at end of file diff --git a/appengine-java11/README.md b/appengine-java11/README.md new file mode 100644 index 00000000000..29b84c82b42 --- /dev/null +++ b/appengine-java11/README.md @@ -0,0 +1,94 @@ +# Google App Engine Standard Environment Samples for Java 11 + + +Open in Cloud Shell + +This is a repository that contains Java code samples for [Google App Engine][ae-docs] +standard Java 11 environment. + +[ae-docs]: https://cloud.google.com/appengine/docs/standard/java11/ + +## Prerequisites + +### Download Maven + +These samples use the [Apache Maven][maven] build system. Before getting +started, be sure to [download][maven-download] and [install][maven-install] it. +When you use Maven as described here, it will automatically download the needed +client libraries. + +[maven]: https://maven.apache.org +[maven-download]: https://maven.apache.org/download.cgi +[maven-install]: https://maven.apache.org/install.html + +### Create a Project in the Google Cloud Platform Console + +If you haven't already created a project, create one now. Projects enable you to +manage all Google Cloud Platform resources for your app, including deployment, +access control, billing, and services. + +1. Open the [Cloud Platform Console][cloud-console]. +1. In the drop-down menu at the top, select **Create a project**. +1. Give your project a name. +1. Make a note of the project ID, which might be different from the project + name. The project ID is used in commands and in configurations. + +[cloud-console]: https://console.cloud.google.com/ + +### Google Cloud Shell, Open JDK 11 setup: + +To switch to an Open JDK 11 in a Cloud shell session, you can use: + +``` + sudo update-alternatives --config java + # And select the usr/lib/jvm/java-11-openjdk-amd64/bin/java version. + # Also, set the JAVA_HOME variable for Maven to pick the correct JDK: + export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 +``` + +## Java 11 runtime + +The simplest way to deploy to App Engine Java 11 is using an executable [Uber JAR][uber-jar]. App Engine will automatically configure the `entrypoint` to run the JAR file. + +* [`springboot-helloworld`](springboot-helloworld): Build a fat JAR with Spring Boot +* [`http-server`](http-server): Build a JAR using the Maven JAR Plugin + +In addition, App Engine allows you to execute the `java` command directly in the `app.yaml` `entrypoint` field, so you can further customize your app's startup. + +* [`custom-entrypoint`](custom-entrypoint): Run a simple server +* [`helloworld-servlet`](helloworld-servlet): Run a WAR package servlet + +With a custom `entrypoint`, you can also construct and package your application as a thin JAR (or an exploded JAR). When you deploy your application, the App Engine plugin will only upload the files that changed, rather than the entire [Uber JAR][uber-jar] package. + +For more information on the Java 11 runtime, see +[Building an App](https://cloud.google.com/appengine/docs/standard/java11/building-app/) +and [Migrating your App Engine app from Java 8 to Java 11](https://cloud.google.com/appengine/docs/standard/java11/java-differences). + + +### Servlet Runtime + +To migrate to the Java 11 runtime, your application must have a +`Main` class that starts a web server. +[`appengine-simple-jetty-main`](appengine-simple-jetty-main) is a shared artifact +that provides a Jetty Web Server for the servlet based runtime. Packaged as a +jar, the Main Class will load a war file, passed as an argument, as the +context root of the web application listening to port 8080. +Some samples create a `.war` which is used as an argument in the +App Engine `app.yaml` entrypoint field. + + +### App Engine Staging Directory + +The App Engine Plugin will stage all the files to upload into App Engine +runtime in `${build.directory}/appengine-staging`. When deploying an +[Uber JAR][uber-jar], the JAR is automatically copied into this staging +directory and uploaded. It's possible to copy other files into this staging +directory (such as additional JVM Agents) and having them available in the +deployed App Engine runtime directory. + +- To stage the files to be uploaded: +``` +mvn appengine:stage +``` + +[uber-jar]: https://stackoverflow.com/questions/11947037/what-is-an-uber-jar diff --git a/appengine-java11/appengine-simple-jetty-main/README.md b/appengine-java11/appengine-simple-jetty-main/README.md new file mode 100644 index 00000000000..9c17c933775 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/README.md @@ -0,0 +1,76 @@ +# Embedded Jetty Server for Google App Engine Standard with Java 11 + +To migrate to the Java 11 runtime, your application must have a +`Main` class that starts a web server. This sample is a shared artifact that +provides a `Main` class to instantiate an HTTP server to run an embedded web +application `WAR` file. + +For more information on the Java 11 runtime, see +[Migrating your App Engine app from Java 8 to Java 11](https://cloud.google.com/appengine/docs/standard/java11/java-differences). + +## Install the dependency +This sample is used as a dependency and must be install locally: +``` +mvn install +``` + +## Using the dependency +See [`helloworld-servlet`](../helloworld-servlet) to see a complete example. + +Your project's `pom.xml` needs to be updated accordingly: + +- Add the `appengine-simple-jetty-main` dependency: +``` + + com.example.appengine.demo + simple-jetty-main + 1 + provided + +``` + +- On deployment, the App Engine runtime uploads files located in +`${build.directory}/appengine-staging`. Add the `maven-dependency-plugin` to +the build in order to copy dependencies to the correct folder: +``` + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + +``` + +To use the dependency add the entrypoint to your `app.yaml` file. The +entrypoint field will start the Jetty server and load your `WAR` file. +``` +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main helloworld.war' +``` + +## Running locally +The [Exec Maven Plugin][exec-plugin] has been added so you can run your +application locally. It is possible to use the [Jetty Maven Plugin][jetty-plugin] +for rapid development and testing, but using the Exec Maven Plugin will ensure +the provided server is running your application as expected. + +- Start the server with your `WAR` file as an argument: +``` +mvn exec:java -Dexec.args="../sample/target/sample.war" +``` + +[jetty-plugin]: https://www.eclipse.org/jetty/documentation/9.4.x/jetty-maven-plugin.html diff --git a/appengine-java11/appengine-simple-jetty-main/pom.xml b/appengine-java11/appengine-simple-jetty-main/pom.xml new file mode 100644 index 00000000000..d1642012804 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + com.example.appengine.demo + simple-jetty-main + simplejettymain-j11 + 1 + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + UTF-8 + 11 + 11 + + + + + + + org.eclipse.jetty + jetty-server + 9.4.18.v20190429 + + + org.eclipse.jetty + jetty-webapp + 9.4.18.v20190429 + jar + + + org.eclipse.jetty + jetty-util + 9.4.18.v20190429 + + + org.eclipse.jetty + jetty-annotations + 9.4.18.v20190429 + jar + + + + org.eclipse.jetty + apache-jsp + 9.4.18.v20190429 + + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + java + + + com.example.appengine.demo.jettymain.Main + + + + + + + diff --git a/appengine-java11/appengine-simple-jetty-main/src/main/java/com/example/appengine/demo/jettymain/Main.java b/appengine-java11/appengine-simple-jetty-main/src/main/java/com/example/appengine/demo/jettymain/Main.java new file mode 100644 index 00000000000..8007fc05740 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/src/main/java/com/example/appengine/demo/jettymain/Main.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 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.appengine.demo.jettymain; + +// [START gae_java11_server] +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.webapp.Configuration.ClassList; +import org.eclipse.jetty.webapp.WebAppContext; + +/** Simple Jetty Main that can execute a WAR file when passed as an argument. */ +public class Main { + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.err.println("Usage: need a relative path to the war file to execute"); + System.exit(1); + } + System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StrErrLog"); + System.setProperty("org.eclipse.jetty.LEVEL", "INFO"); + + // Create a basic Jetty server object that will listen on port 8080. + // Note: If you set this to port 0, a randomly available port will be + // assigned. You can find the assigned port in the logs or programmatically + // obtain it. + Server server = new Server(8080); + + // The WebAppContext is the interface to provide configuration for a web + // application. In this example, the context path is being set to "/" so + // it is suitable for serving root context requests. + WebAppContext webapp = new WebAppContext(); + webapp.setContextPath("/"); + webapp.setWar(args[0]); + ClassList classlist = ClassList.setServerDefault(server); + + // Enable Annotation Scanning. + classlist.addBefore( + "org.eclipse.jetty.webapp.JettyWebXmlConfiguration", + "org.eclipse.jetty.annotations.AnnotationConfiguration"); + + // Set the the WebAppContext as the ContextHandler for the server. + server.setHandler(webapp); + + // Start the server! By using the server.join() the server thread will + // join with the current thread. See + // "http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#join()" + // for more details. + server.start(); + server.join(); + } +} +// [END gae_java11_server] diff --git a/appengine-java11/cloudsql/README.md b/appengine-java11/cloudsql/README.md new file mode 100644 index 00000000000..cc5cbff7043 --- /dev/null +++ b/appengine-java11/cloudsql/README.md @@ -0,0 +1,72 @@ +# Connecting to Cloud SQL - MySQL with Java 11 on Google App Engine Standard + +This sample demonstrates how to use +[Cloud SQL - MySQL](https://cloud.google.com/sql/docs/mysql/) on +Google App Engine Standard. + +## Code + +The sample code is located in `java-docs-samples/cloud-sql/mysql/servlet`. This directory has the supplemental files needed to deploy to Google App Engine Standard with Java 11. + +## Setup your Cloud SQL Database + +- Create a 2nd Gen Cloud SQL Instance by following these +[instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note the connection string, +database user, and database password that you create. + +- Create a database for your application by following these +[instructions](https://cloud.google.com/sql/docs/mysql/create-manage-databases). Note the database +name. + +- Create a service account with the 'Cloud SQL Client' permissions by following these +[instructions](https://cloud.google.com/sql/docs/mysql/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). +Download a JSON key to use to authenticate your connection. + +## Setup the App + +- See [Prerequisites](../README.md#Prerequisites). + +- Add the [appengine-simple-jetty-main](../README.md#appengine-simple-jetty-main) +Main class to your classpath: +``` + cd java-docs-samples/appengine-java11/appengine-simple-jetty-main + mvn install +``` + +- Move into the sample directory: +``` +cd ../../cloud-sql/mysql/servlet/ +``` + +- In the new Java 11 runtime, you must remove your `appengine-web.xml` file and create an `app.yaml` file to configure your application settings. Create an `src/main/appengine` directory and copy the `app.yaml` provided: +```bash +mkdir src/main/appengine +cp ../../../appengine-java11/cloudsql/app.yaml src/main/appengine/ +``` + +- Use the information from creating your database to replace the +environment variables in your `app.yaml`: +```YAML +CLOUD_SQL_CONNECTION_NAME: '::' +DB_NAME: 'my_db' +DB_USER: 'my-db-user' +DB_PASS: 'my-db-pass' +``` + +- Java 11 has specific requirements on packaging your app. Replace the `pom.xml` with the Java 11 `pom.xml`: +```bash +cp ../../../appengine-java11/cloudsql/pom.xml ./ +``` + +### Deploy to Google Cloud + +The following command will deploy the application to your Google Cloud project: +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +View your application: +``` +gcloud app browse +``` +or by visiting `https://.appspot.com`. diff --git a/appengine-java11/cloudsql/app.yaml b/appengine-java11/cloudsql/app.yaml new file mode 100644 index 00000000000..7c49d4074a8 --- /dev/null +++ b/appengine-java11/cloudsql/app.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main cloudsql.war' + +env_variables: + CLOUD_SQL_CONNECTION_NAME: "my-project:region:instance" + DB_NAME: "my_db" + DB_USER: "my-db-user" + DB_PASS: "my-db-password" diff --git a/appengine-java11/cloudsql/pom.xml b/appengine-java11/cloudsql/pom.xml new file mode 100644 index 00000000000..ac52c07b2fc --- /dev/null +++ b/appengine-java11/cloudsql/pom.xml @@ -0,0 +1,147 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.cloudsql + cloudsql + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + false + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + javax.servlet + jstl + 1.2 + + + org.slf4j + slf4j-simple + 1.7.25 + provided + + + + mysql + mysql-connector-java + 8.0.11 + provided + + + com.google.cloud.sql + mysql-socket-factory-connector-j-8 + 1.0.12 + provided + + + com.zaxxer + HikariCP + 3.3.0 + provided + + + + + cloudsql + + + org.apache.maven.plugins + maven-war-plugin + 3.2.2 + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + maven-resources-plugin + 2.7 + + + copy-resources + install + + copy-resources + + + ${project.build.directory}/appengine-staging/cprof + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + cloudsql + + + + + diff --git a/appengine-java11/custom-entrypoint/Main.java b/appengine-java11/custom-entrypoint/Main.java new file mode 100644 index 00000000000..7f83c5c3c76 --- /dev/null +++ b/appengine-java11/custom-entrypoint/Main.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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. + */ + +// [START gae_java11_simple_server] +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class Main { + + public static void main(String[] args) throws IOException { + // Create an instance of HttpServer bound to port 8080. + HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); + + // Set root URI path. + server.createContext("/", (var t) -> { + byte[] response = "Hello World from Google App Engine Java 11.".getBytes(); + t.sendResponseHeaders(200, response.length); + try (OutputStream os = t.getResponseBody()) { + os.write(response); + } + }); + + // Start the server. + server.start(); + } +} +// [END gae_java11_simple_server] diff --git a/appengine-java11/custom-entrypoint/README.md b/appengine-java11/custom-entrypoint/README.md new file mode 100644 index 00000000000..69e857258af --- /dev/null +++ b/appengine-java11/custom-entrypoint/README.md @@ -0,0 +1,20 @@ +# Using a Custom Entrypoint on Google App Engine Standard with Java 11 + +This sample shows how to deploy an application to Google App Engine, using the +`entrypoint` element in the [app.yaml](app.yaml) to start your application. The +sample uses the `java` command is used to compile and execute the Java source code. + +## Setup +See [Prerequisites](../README.md#Prerequisites). + +## Deploy to App Engine Standard + +``` +gcloud app deploy +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/custom-entrypoint/app.yaml b/appengine-java11/custom-entrypoint/app.yaml new file mode 100644 index 00000000000..79b75f6c3e8 --- /dev/null +++ b/appengine-java11/custom-entrypoint/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +# [START gae_java11_custom_entrypoint] +runtime: java11 +entrypoint: java Main.java +# [END gae_java11_custom_entrypoint] diff --git a/appengine-java11/gaeinfo/README.md b/appengine-java11/gaeinfo/README.md new file mode 100644 index 00000000000..4117413536b --- /dev/null +++ b/appengine-java11/gaeinfo/README.md @@ -0,0 +1,57 @@ +# Google App Engine Information App for Java11 + + +Open in Cloud Shell + +This sample demonstrates how to show all system environment metadata and properties on Google App +Engine standard app. + +## Setup your Google Cloud Platform Project + +* If you haven't already, Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/) + + `gcloud init` + +* If you haven't already, Create an App Engine app within the current Google Cloud Project + + `gcloud app create` + +* If you haven't already, Setup [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials) + + `gcloud auth application-default login` + +## Setup the Sample App + +- Copy the sample apps to your local machine: +``` + git clone https://github.com/GoogleCloudPlatform/java-docs-samples +``` + +- Add the [appengine-simple-jetty-main](../README.md#appengine-simple-jetty-main) +Main class to your classpath: +``` + cd java-docs-samples/appengine-java11/appengine-simple-jetty-main + mvn install +``` + +- Move into the `appengine-java11/gaeinfo` directory and compile the app: +``` + cd ../gaeinfo + mvn package +``` + +## Deploy + +- Deploy to App Engine standard environment using the following Maven command. +``` + mvn appengine:deploy -Dapp.deploy.projectId= +``` +- Direct your browser to `https://.appspot.com`. +- View more in-depth metrics data on the [StackDriver Monitoring Dashboard][dashboard] + +Note: The first time the app is run (or after any metrics definitions have +been deleted) it may take up to 5 minutes for the MetricDescriptors to sync +with StackDriver before any results are shown. If you do not see results, +please wait a few moments and try again. + +[dashboard]: https://console.cloud.google.com/monitoring diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml new file mode 100644 index 00000000000..d977e263758 --- /dev/null +++ b/appengine-java11/gaeinfo/pom.xml @@ -0,0 +1,136 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + appengine-gaeinfo-j11 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + com.squareup.okhttp3 + okhttp + 3.12.1 + provided + + + + com.google.code.gson + gson + 2.8.5 + provided + + + + org.thymeleaf + thymeleaf + 3.0.11.RELEASE + provided + + + + + gaeinfo + + + org.apache.maven.plugins + maven-war-plugin + 3.2.2 + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + maven-resources-plugin + 2.7 + + + copy-resources + install + + copy-resources + + + ${project.build.directory}/appengine-staging/cprof + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + gaeinfo + + + + + + diff --git a/appengine-java11/gaeinfo/src/main/appengine/app.yaml b/appengine-java11/gaeinfo/src/main/appengine/app.yaml new file mode 100644 index 00000000000..a98633567cc --- /dev/null +++ b/appengine-java11/gaeinfo/src/main/appengine/app.yaml @@ -0,0 +1,17 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main gaeinfo.war' diff --git a/appengine-java11/gaeinfo/src/main/java/com/example/appengine/standard/GaeInfoServlet.java b/appengine-java11/gaeinfo/src/main/java/com/example/appengine/standard/GaeInfoServlet.java new file mode 100644 index 00000000000..90c040aae9a --- /dev/null +++ b/appengine-java11/gaeinfo/src/main/java/com/example/appengine/standard/GaeInfoServlet.java @@ -0,0 +1,179 @@ +/* + * Copyright 2019 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.appengine.standard; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParser; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; +import java.util.concurrent.TimeUnit; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.WebContext; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +@SuppressWarnings({"serial"}) +@WebServlet( + name = "GAEInfo", + description = "GAEInfo: Write info about GAE Standard", + urlPatterns = "/") +public class GaeInfoServlet extends HttpServlet { + + private final String[] metaPath = { + "/computeMetadata/v1/project/numeric-project-id", + "/computeMetadata/v1/project/project-id", + "/computeMetadata/v1/instance/zone", + "/computeMetadata/v1/instance/service-accounts/default/aliases", + "/computeMetadata/v1/instance/service-accounts/default/", + "/computeMetadata/v1/instance/service-accounts/default/scopes", + // Tokens work - but are a security risk to display + // "/computeMetadata/v1/instance/service-accounts/default/token" + }; + + final String[] metaServiceAcct = { + "/computeMetadata/v1/instance/service-accounts/{account}/aliases", + "/computeMetadata/v1/instance/service-accounts/{account}/email", + "/computeMetadata/v1/instance/service-accounts/{account}/scopes", + // Tokens work - but are a security risk to display + // "/computeMetadata/v1/instance/service-accounts/{account}/token" + }; + + private final String metadata = "http://metadata.google.internal"; + + private TemplateEngine templateEngine; + + // Use OkHttp from Square as it's quite easy to use for simple fetches. + private final OkHttpClient ok = + new OkHttpClient.Builder() + .readTimeout(500, TimeUnit.MILLISECONDS) // Don't dawdle + .writeTimeout(500, TimeUnit.MILLISECONDS) + .build(); + + // Setup to pretty print returned json + private final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + private final JsonParser jp = new JsonParser(); + + // Fetch Metadata + String fetchMetadata(String key) throws IOException { + Request request = + new Request.Builder() + .url(metadata + key) + .addHeader("Metadata-Flavor", "Google") + .get() + .build(); + + Response response = ok.newCall(request).execute(); + return response.body().string(); + } + + String fetchJsonMetadata(String prefix) throws IOException { + Request request = + new Request.Builder() + .url(metadata + prefix) + .addHeader("Metadata-Flavor", "Google") + .get() + .build(); + + Response response = ok.newCall(request).execute(); + + // Convert json to prety json + return gson.toJson(jp.parse(response.body().string())); + } + + @Override + public void init() { + // Setup ThymeLeaf + ServletContextTemplateResolver templateResolver = + new ServletContextTemplateResolver(this.getServletContext()); + + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setCacheTTLMs(1200000L); // TTL=20m + + // Cache is set to true by default. Set to false if you want templates to + // be automatically updated when modified. + templateResolver.setCacheable(true); + + templateEngine = new TemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String key; + WebContext ctx = new WebContext(req, resp, getServletContext(), req.getLocale()); + + resp.setContentType("text/html"); + + TreeMap m = new TreeMap<>(); + + for (Enumeration e = req.getHeaderNames(); e.hasMoreElements(); ) { + key = e.nextElement(); + m.put(key, req.getHeader(key)); + } + ctx.setVariable("headers", m); + + Cookie[] cookies = req.getCookies(); + m = new TreeMap<>(); + if (cookies != null && cookies.length != 0) { + for (Cookie co : cookies) { + m.put(co.getName(), co.getValue()); + } + } + ctx.setVariable("cookies", m); + + Properties properties = System.getProperties(); + m = new TreeMap<>(); + for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) { + key = (String) e.nextElement(); + m.put(key, (String) properties.get(key)); + } + ctx.setVariable("systemprops", m); + + Map envVar = System.getenv(); + m = new TreeMap<>(envVar); + ctx.setVariable("envvar", m); + + // The metadata server is only on a production system + m = new TreeMap<>(); + for (String k : metaPath) { + m.put(k, fetchMetadata(k)); + } + ctx.setVariable("Metadata", m.descendingMap()); + + ctx.setVariable("sam", m.descendingMap()); + + // Recursivly get all info about service accounts -- Note tokens are leftout by default. + ctx.setVariable( + "rsa", fetchJsonMetadata("/computeMetadata/v1/instance/service-accounts/?recursive=true")); + // Recursivly get all data on Metadata server. + ctx.setVariable("ram", fetchJsonMetadata("/?recursive=true")); + + templateEngine.process("index", ctx, resp.getWriter()); + } +} diff --git a/appengine-java11/gaeinfo/src/main/webapp/WEB-INF/templates/index.html b/appengine-java11/gaeinfo/src/main/webapp/WEB-INF/templates/index.html new file mode 100644 index 00000000000..d54344ab6f4 --- /dev/null +++ b/appengine-java11/gaeinfo/src/main/webapp/WEB-INF/templates/index.html @@ -0,0 +1,84 @@ + + + + + App Engine Java11 Standard Metadata + + + +

Environment Attributes

+ + + + + +
+

Headers

+ + + + + + +
+

Cookies

+ + + + + + +
+

Java System Properties

+ + + + + + +
+

Environment Variables

+ + + + + +
+ +

Metadata

+ + + + + +
+

Service Account Metadata

+ + + + + +
+

Recursive service-accounts

+
+

Recursive all metadata

+
+ + + diff --git a/appengine-java11/guestbook-cloud-firestore/README.md b/appengine-java11/guestbook-cloud-firestore/README.md new file mode 100644 index 00000000000..8f1e068ebb5 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/README.md @@ -0,0 +1,77 @@ +# Guestbook sample for Google App Engine Java 11 + + +Open in Cloud Shell + +This sample demonstrates how to handle form data using +[Cloud Firestore](https://cloud.google.com/firestore/) on Google App Engine +Standard. + +This sample also uses packages from [Guava](https://github.com/google/guava), +which provides some basic utility libraries and collections from Google's core +libraries. + +## Setup your Google Cloud Platform Project + +* Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/) + + `gcloud init` + +* If this is your first time creating an App Engine application: +``` + gcloud app create +``` + +## Setup the Sample App + +- Copy the sample apps to your local machine: +``` + git clone https://github.com/GoogleCloudPlatform/java-docs-samples +``` + +- Add the [appengine-simple-jetty-main](../README.md#appengine-simple-jetty-main) +Main class to your classpath: +``` + cd java-docs-samples/appengine-java11/appengine-simple-jetty-main + mvn install +``` + +- Move into the `appengine-java11/guestbook-cloud-firestore` directory and compile the app: +``` + cd ../guestbook-cloud-firestore + mvn package +``` + +* Setup [Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials) by +[creating a service account](https://cloud.google.com/docs/authentication/production#creating_a_service_account) and downloading the JSON key file. + + * Provide authentication credentials to your application code by setting the + environment variable `GOOGLE_APPLICATION_CREDENTIALS` to the path of your + JSON key file. + + `export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"` + +* Replace `YOUR-PROJECT-ID` in [`Persistence.java`](/src/main/java/com/example/guestbook/Persistence.java) with your project Id you created. + +* Create a [Cloud Firestore in Native mode](https://cloud.google.com/firestore/docs/firestore-or-datastore) database by going to the +[Cloud Firestore UI](https://console.cloud.google.com/firestore/data) and +from the Select a database service screen: + * Choose Cloud Firestore in Native mode. + * Select a Cloud Firestore location. + * Click Create Database. + +**Cloud Firestore and App Engine:** You can't use both Cloud Firestore and Cloud Datastore in the same project, which might affect apps using App Engine. Try using Cloud Firestore with a different project if you need to use Cloud Datastore. + +## Deploying + +Deploy your application using the maven plugin: + +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +View your application: +``` +gcloud app browse +``` +or by visiting `https://.appspot.com`. diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml new file mode 100644 index 00000000000..fbd3870036d --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -0,0 +1,117 @@ + + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.guestbook + guestbook-cloud-firestore + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + + com.google.cloud + google-cloud-firestore + 0.81.0-beta + provided + + + + com.google.guava + guava + 27.1-jre + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + jstl + jstl + 1.2 + + + + + guestbook + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + guestbook + + + + + org.eclipse.jetty + jetty-maven-plugin + 9.4.2.v20170220 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + + diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml new file mode 100644 index 00000000000..319f597f761 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +# [START gae_java11_firestore_yaml] +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main guestbook.war' +# [END gae_java11_firestore_yaml] diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Greeting.java b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Greeting.java new file mode 100644 index 00000000000..df7872751e1 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Greeting.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 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.guestbook; + +import com.google.common.base.MoreObjects; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** Represents a greeting: id, guestbook reference, author, content, date. */ +@SuppressWarnings("JavadocMethod") +public class Greeting { + + private Guestbook book; + + public String id; + public String authorName; + public String content; + public Date date; + + public Greeting() { + date = new Date(); + } + + public Greeting(String book, String content) { + this(); + this.book = new Guestbook(book); + this.content = content; + } + + public Greeting(String book, String content, String name) { + this(book, content); + authorName = name; + } + + /** Save the Greeting in the guestbook */ + public void save() { + // [START gae_java11_firestore_greeting] + // Construct a Greeting. + Map greetingData = new HashMap<>(); + greetingData.put("date", date); + greetingData.put("content", content); + greetingData.put("authorName", authorName); + + // Add Greeting to Guestbook with random id. + book.getBookRef().collection("Greetings").add(greetingData); + // [END gae_java11_firestore_greeting] + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + Greeting greeting = (Greeting) obj; + return Objects.equals(id, greeting.id) + && Objects.equals(authorName, greeting.authorName) + && Objects.equals(content, greeting.content) + && Objects.equals(date, greeting.date); + } + + @Override + public int hashCode() { + return Objects.hash(id, authorName, content, date); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("id", id) + .add("authorName", authorName) + .add("content", content) + .add("date", date) + .add("book", book) + .toString(); + } +} diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Guestbook.java b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Guestbook.java new file mode 100644 index 00000000000..d7932c8166f --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Guestbook.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 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.guestbook; + +import static com.example.guestbook.Persistence.getFirestore; + +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.Query.Direction; +import com.google.cloud.firestore.QueryDocumentSnapshot; +import com.google.cloud.firestore.QuerySnapshot; +import com.google.common.base.MoreObjects; +import com.google.common.collect.ImmutableList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** Represents a guestbook: book name, book document reference. */ +@SuppressWarnings("JavadocMethod") +public class Guestbook { + + private static final long TIMEOUT_SECONDS = 5; + + private final DocumentReference bookRef; + + public final String book; + + public Guestbook(String book) { + this.book = book == null ? "default" : book; + // Construct the Guestbook data. + Map bookData = new HashMap<>(); + bookData.put("name", this.book); + // [START gae_java11_firestore_book] + // The Guestbook document reference in the collection. + bookRef = getFirestore().collection("Guestbooks").document(this.book); + // Add the Guestbook to collection. + bookRef.set(bookData); + // [END gae_java11_firestore_book] + } + + /** Get the Firestore reference to the Guestbook document **/ + public DocumentReference getBookRef() { + return bookRef; + } + + // [START gae_java11_firestore_get_greetings] + /** Query Firstore for Guestbook greetings */ + public List getGreetings() { + // Initialize a List for Greetings. + ImmutableList.Builder greetings = new ImmutableList.Builder(); + // Construct query. + ApiFuture query = + bookRef.collection("Greetings").orderBy("date", Direction.DESCENDING).get(); + + try { + // Get query documents. + QuerySnapshot querySnapshot = query.get(); + for (QueryDocumentSnapshot greeting : querySnapshot.getDocuments()) { + greetings.add(greeting.toObject(Greeting.class)); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + + return greetings.build(); + } + // [END gae_java11_firestore_get_greetings] + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Guestbook)) { + return false; + } + Guestbook guestbook = (Guestbook) obj; + return Objects.equals(book, guestbook.book) && Objects.equals(bookRef, guestbook.bookRef); + } + + @Override + public int hashCode() { + return Objects.hash(book, bookRef); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this).add("book", book).add("bookRef", bookRef).toString(); + } +} diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Persistence.java b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Persistence.java new file mode 100644 index 00000000000..fefbf40503a --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Persistence.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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.guestbook; + +// [START gae_java11_firestore_dependencies] +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +// [END gae_java11_firestore_dependencies] + +/** Create a persistence connection to your Firestore instance. */ +public class Persistence { + + private static Firestore firestore; + + @SuppressWarnings("JavadocMethod") + public static Firestore getFirestore() { + if (firestore == null) { + // Authorized Firestore service + // [START gae_java11_firestore] + Firestore db = + FirestoreOptions.newBuilder().setProjectId("YOUR-PROJECT-ID").build().getService(); + // [END gae_java11_firestore] + firestore = db; + } + + return firestore; + } + + public static void setFirestore(Firestore firestore) { + Persistence.firestore = firestore; + } +} diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/SignGuestbookServlet.java b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/SignGuestbookServlet.java new file mode 100644 index 00000000000..7092bc2c139 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/SignGuestbookServlet.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 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.guestbook; + +// [START gae_java11_form_data] +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** Servlet to sace the form data to your Firestore instance. */ +@SuppressWarnings("serial") +@WebServlet(name = "SignGuestbookServlet", value = "/sign") +public class SignGuestbookServlet extends HttpServlet { + + // Process the HTTP POST of the form + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + Greeting greeting; + + String guestbookName = req.getParameter("guestbookName"); + String name = req.getParameter("name"); + String content = req.getParameter("content"); + + greeting = new Greeting(guestbookName, content, name); + greeting.save(); + + resp.sendRedirect("/index.jsp?guestbookName=" + guestbookName); + } +} +// [END gae_java11_form_data] diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/WEB-INF/web.xml b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..211f89c251d --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,23 @@ + + + + + + index.jsp + + diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp new file mode 100644 index 00000000000..9b5bfa84e4f --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp @@ -0,0 +1,107 @@ + + + + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + +<%@ page import="com.example.guestbook.Greeting" %> +<%@ page import="com.example.guestbook.Guestbook" %> +<%@ page import="java.util.List" %> + +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> + + + + + Guestbook - Google App Engine Standard + + + <% + // Get the guestbook name. + String guestbookName = request.getParameter("guestbookName"); + if (guestbookName == null || guestbookName.equals(null) || guestbookName.equals("")) { + guestbookName = "default"; + } + pageContext.setAttribute("guestbookName", guestbookName); + + // Create a Guestbook object. + Guestbook theBook = new Guestbook(guestbookName); + + // Run an query to ensure we see the most up-to-date + // view of the Greetings belonging to the selected Guestbook. + List greetings = theBook.getGreetings(); + %> + +

Welcome to the '${fn:escapeXml(guestbookName)}' Guestbook

+ + <%-- Switch Guestbook --%> +
+
+
+
+ + <%-- Guestbook form --%> +

Write Your Greeting

+ <%-- [START gae_java11_form] --%> +
+
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+ <%-- [END gae_java11_form] --%> + + <%-- List greetings --%> +

Greetings:

+ + <% if (greetings.isEmpty()) { %> +

The guestbook has no greetings.

+ <% + } else { + for (Greeting greeting : greetings) { + pageContext.setAttribute("greeting_content", greeting.content); + pageContext.setAttribute("greeting_date", greeting.date); + + String author; + if (greeting.authorName.equals("")) { + author = "Anonymous"; + } else { + author = greeting.authorName; + } + pageContext.setAttribute("greeting_name", author); + %> +
+ ${fn:escapeXml(greeting_name)} +

${fn:escapeXml(greeting_date)}

+
${fn:escapeXml(greeting_content)}
+
+ <% + } + } + %> + + + diff --git a/appengine-java11/helloworld-servlet/README.md b/appengine-java11/helloworld-servlet/README.md new file mode 100644 index 00000000000..8fc05445d83 --- /dev/null +++ b/appengine-java11/helloworld-servlet/README.md @@ -0,0 +1,99 @@ +# Hello World Servlet on Google App Engine Standard with Java 11 + +This sample demonstrates migrating a `WAR` packaged servlet +to Java 11. To migrate to the Java 11 runtime, your application must have a +`Main` class that starts a web server. This sample is dependent on artifact +[`appengine-simple-jetty-main`](../appengine-simple-jetty-main) to provide a +`Main` class that starts an embedded Jetty server. + +## Setup + +The `pom.xml` has been updated accordingly: +- Update maven compiler to use Java version 11: +``` + + 11 + 11 + false + +``` + +- Add the `appengine-simple-jetty-main` dependency: +``` + + com.example.appengine.demo + simple-jetty-main + 1 + provided + +``` +**Note: this dependency needs to be installed locally.** + +- On deployment, the App Engine runtime uploads files located in +`${build.directory}/appengine-staging`. Add the `maven-dependency-plugin` to +the build in order to copy dependencies to the correct folder: +``` + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + +``` + +The `appengine-web.xml` file has been removed and an +[`app.yaml`](src/main/appengine/app.yaml) has been added to manage your +application settings: +- The entrypoint field will start the Jetty server and load your `WAR` file. +``` +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main helloworld.war' +``` + +## Running locally +The `exec-maven-plugin` has been added to `appengine-simple-jetty-main` so you +can run your application locally. + +- Package your app: +``` +mvn clean package +``` + +- Move into the directory: +``` +cd ../appengine-simple-jetty-main +``` + +- Install the dependency: +``` +mvn install +``` + +- Start the server with your `WAR` file as an argument: +``` +mvn exec:java -Dexec.args="../helloworld-java8/target/helloworld.war" +``` + +Then visit: http://localhost:8080/hello + +## Deploying +While in the `helloworld-servlet` directory, use the `appengine-maven-plugin` to +deploy your app: +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` +Then visit: https://YOUR-PROJECT-ID.appspot.com/hello diff --git a/appengine-java11/helloworld-servlet/pom.xml b/appengine-java11/helloworld-servlet/pom.xml new file mode 100644 index 00000000000..e1e26f773d5 --- /dev/null +++ b/appengine-java11/helloworld-servlet/pom.xml @@ -0,0 +1,103 @@ + + + + 4.0.0 + war + com.example.appengine + helloworld-servlet + 1.0-SNAPSHOT + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + + 11 + 11 + false + + + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + + helloworld + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + helloworld + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + + + + diff --git a/appengine-java11/helloworld-servlet/src/main/appengine/app.yaml b/appengine-java11/helloworld-servlet/src/main/appengine/app.yaml new file mode 100644 index 00000000000..a2e5faac0fc --- /dev/null +++ b/appengine-java11/helloworld-servlet/src/main/appengine/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +# [START gae_java11_servlet_yaml] +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main helloworld.war' +# [END gae_java11_servlet_yaml] diff --git a/appengine-java11/helloworld-servlet/src/main/java/com/example/appengine/HelloAppEngine.java b/appengine-java11/helloworld-servlet/src/main/java/com/example/appengine/HelloAppEngine.java new file mode 100644 index 00000000000..600c7771bd4 --- /dev/null +++ b/appengine-java11/helloworld-servlet/src/main/java/com/example/appengine/HelloAppEngine.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 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.appengine; + +import java.io.IOException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet(name = "HelloAppEngine", value = "/hello") +public class HelloAppEngine extends HttpServlet { + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + + response.setContentType("text/html"); + response.getWriter().println("

Hello, Google App Engine with Java 11!

"); + } +} diff --git a/appengine-java11/http-server/README.md b/appengine-java11/http-server/README.md new file mode 100644 index 00000000000..b27ea236705 --- /dev/null +++ b/appengine-java11/http-server/README.md @@ -0,0 +1,21 @@ +# Standalone HTTP Server on Google App Engine Standard with Java 11 + +This sample shows how to deploy an application to Google App Engine using the +a fat jar. There is no `entrypoint` field listed in the [`app.yaml`](src/main/appengine/app.yaml), +as the application is a single fat jar with the correct MainClass field in the MANIFEST. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploy to App Engine Standard + +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/http-server/pom.xml b/appengine-java11/http-server/pom.xml new file mode 100644 index 00000000000..2a059349a70 --- /dev/null +++ b/appengine-java11/http-server/pom.xml @@ -0,0 +1,47 @@ + + 4.0.0 + com.example.appengine + http-server + 0.1 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + + 11 + 11 + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.1 + + + + com.example.appengine.Main + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + http-server + + + + + diff --git a/appengine-java11/http-server/src/main/appengine/app.yaml b/appengine-java11/http-server/src/main/appengine/app.yaml new file mode 100644 index 00000000000..22c1d8e31f5 --- /dev/null +++ b/appengine-java11/http-server/src/main/appengine/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +# [START gae_java11_runtime] +runtime: java11 +# No need for an entrypoint with single fatjar with correct manifest class-path entry. +# [END gae_java11_runtime] diff --git a/appengine-java11/http-server/src/main/java/com/example/appengine/Main.java b/appengine-java11/http-server/src/main/java/com/example/appengine/Main.java new file mode 100644 index 00000000000..b0bbfb76f7e --- /dev/null +++ b/appengine-java11/http-server/src/main/java/com/example/appengine/Main.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 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.appengine; + +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class Main { + + public static void main(String[] args) throws IOException { + // Create an instance of HttpServer with port 8080. + HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); + + // Set root URI path. + server.createContext("/", (var t) -> { + byte[] response = "Hello World!".getBytes(); + t.sendResponseHeaders(200, response.length); + try (OutputStream os = t.getResponseBody()) { + os.write(response); + } + }); + + // Create a second URI path. + server.createContext("/foo", (var t) -> { + byte[] response = "Foo!".getBytes(); + t.sendResponseHeaders(200, response.length); + try (OutputStream os = t.getResponseBody()) { + os.write(response); + } + }); + + server.start(); + } +} diff --git a/appengine-java11/kotlin-ktor/README.md b/appengine-java11/kotlin-ktor/README.md new file mode 100644 index 00000000000..8405870bcd4 --- /dev/null +++ b/appengine-java11/kotlin-ktor/README.md @@ -0,0 +1,20 @@ +# Ktor Application on Google App Engine Standard with Kotlin + +This sample shows how to deploy a [Ktor](https://ktor.io/) +application to Google App Engine standard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/kotlin-ktor/app.yaml b/appengine-java11/kotlin-ktor/app.yaml new file mode 100644 index 00000000000..2494511e3d7 --- /dev/null +++ b/appengine-java11/kotlin-ktor/app.yaml @@ -0,0 +1,17 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 +entrypoint: 'java -Xmx32m -jar kotlin-ktor-0.0.1-jar-with-dependencies.jar' diff --git a/appengine-java11/kotlin-ktor/pom.xml b/appengine-java11/kotlin-ktor/pom.xml new file mode 100644 index 00000000000..3a2a4d23608 --- /dev/null +++ b/appengine-java11/kotlin-ktor/pom.xml @@ -0,0 +1,179 @@ + + + + 4.0.0 + com.example.appengine + kotlin-ktor + 0.0.1 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + official + UTF-8 + true + io.ktor.server.netty.EngineMain + 11 + 11 + + + + + repo1 + https://jcenter.bintray.com + true + true + + + repo2 + https://kotlin.bintray.com/ktor + true + true + + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + 1.3.30 + + + io.ktor + ktor-server-netty + 1.1.3 + + + ch.qos.logback + logback-classic + 1.2.3 + + + io.ktor + ktor-server-core + 1.1.3 + + + io.ktor + ktor-server-host-common + 1.1.3 + + + io.ktor + ktor-server-tests + 1.1.3 + test + + + + + ${project.basedir}/src + ${project.basedir}/test + + + ${project.basedir}/resources + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + maven-compiler-plugin + 1.81.8 + + + kotlin-maven-plugin + org.jetbrains.kotlin + 1.3.30 + + + compile + compile + + enable + + + + test-compile + test-compile + + enable + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + + + true + ${main.class} + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.6 + + + make-assembly + package + single + + + + ${main.class} + + + + jar-with-dependencies + + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + kotlin-ktor + + ./ + + ${project.build.directory}/${project.build.finalName}-jar-with-dependencies.jar + + + + + diff --git a/appengine-java11/kotlin-ktor/resources/application.conf b/appengine-java11/kotlin-ktor/resources/application.conf new file mode 100644 index 00000000000..43b1e3a472e --- /dev/null +++ b/appengine-java11/kotlin-ktor/resources/application.conf @@ -0,0 +1,25 @@ +# Copyright 2019 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. + +ktor { + deployment { + port = 8080 + port = ${?PORT} + + shutdown.url = "/_ah/stop" + } + application { + modules = [ com.example.appengine.ApplicationKt.module ] + } +} diff --git a/appengine-java11/kotlin-ktor/resources/logback.xml b/appengine-java11/kotlin-ktor/resources/logback.xml new file mode 100644 index 00000000000..377f3010c5d --- /dev/null +++ b/appengine-java11/kotlin-ktor/resources/logback.xml @@ -0,0 +1,28 @@ + + + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/appengine-java11/kotlin-ktor/src/Application.kt b/appengine-java11/kotlin-ktor/src/Application.kt new file mode 100644 index 00000000000..5d0ce8bb3dd --- /dev/null +++ b/appengine-java11/kotlin-ktor/src/Application.kt @@ -0,0 +1,45 @@ +// Copyright 2019 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.appengine + +import io.ktor.application.* +import io.ktor.response.* +import io.ktor.request.* +import io.ktor.routing.* +import io.ktor.http.* +import io.ktor.content.* +import io.ktor.http.content.* +import io.ktor.server.engine.* + +fun main(args: Array): Unit = io.ktor.server.netty.EngineMain.main(args) + +@Suppress("unused") // Referenced in application.conf +@kotlin.jvm.JvmOverloads +fun Application.module(testing: Boolean = false) { + install(ShutDownUrl.ApplicationCallFeature) { + // The URL that will be intercepted. You can also use the + // application.conf's ktor.deployment.shutdown.url key. + shutDownUrl = "/_ah/stop" + + // A function that will be executed to get the exit code of the process + exitCodeSupplier = { 0 } // ApplicationCall.() -> Int + } + + routing { + get("/") { + call.respondText("Hello World!", contentType = ContentType.Text.Plain) + } + } +} diff --git a/appengine-java11/kotlin-ktor/test/ApplicationTest.kt b/appengine-java11/kotlin-ktor/test/ApplicationTest.kt new file mode 100644 index 00000000000..32cb9aff1af --- /dev/null +++ b/appengine-java11/kotlin-ktor/test/ApplicationTest.kt @@ -0,0 +1,38 @@ +// Copyright 2019 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.appengine + +import io.ktor.application.* +import io.ktor.response.* +import io.ktor.request.* +import io.ktor.routing.* +import io.ktor.http.* +import io.ktor.content.* +import io.ktor.http.content.* +import io.ktor.server.engine.* +import kotlin.test.* +import io.ktor.server.testing.* + +class ApplicationTest { + @Test + fun testRoot() { + withTestApplication({ module(testing = true) }) { + handleRequest(HttpMethod.Get, "/").apply { + assertEquals(HttpStatusCode.OK, response.status()) + assertEquals("Hello World!", response.content) + } + } + } +} diff --git a/appengine-java11/micronaut-helloworld/README.md b/appengine-java11/micronaut-helloworld/README.md new file mode 100644 index 00000000000..975875c96e4 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/README.md @@ -0,0 +1,20 @@ +# Micronaut Application on Google App Engine Standard with Java 11 + +This sample shows how to deploy a [Micronaut](https://micronaut.io/index.html) +application to Google App Engine standard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/micronaut-helloworld/micronaut-cli.yml b/appengine-java11/micronaut-helloworld/micronaut-cli.yml new file mode 100644 index 00000000000..6e962c74045 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/micronaut-cli.yml @@ -0,0 +1,19 @@ +# Copyright 2019 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. + +profile: service +defaultPackage: com.example.appengine +--- +testFramework: junit +sourceLanguage: java diff --git a/appengine-java11/micronaut-helloworld/pom.xml b/appengine-java11/micronaut-helloworld/pom.xml new file mode 100644 index 00000000000..dfdb821c8c6 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/pom.xml @@ -0,0 +1,217 @@ + + + + 4.0.0 + com.example.appengine + micronaut-helloworld + 0.1 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + UTF-8 + com.example.appengine.Application + 11 + 11 + + + + + + io.micronaut + micronaut-bom + 1.1.0 + pom + import + + + + + + + io.micronaut + micronaut-inject + compile + + + io.micronaut + micronaut-validation + compile + + + io.micronaut + micronaut-runtime + compile + + + io.micronaut + micronaut-http-client + compile + + + javax.annotation + javax.annotation-api + compile + + + io.micronaut + micronaut-http-server-netty + compile + + + ch.qos.logback + logback-classic + 1.2.3 + runtime + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + io.micronaut.test + micronaut-test-junit5 + test + + + junit + junit + 4.4 + test + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + micronaut-helloworld + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + + + ${exec.mainClass} + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + java + + -noverify + -XX:TieredStopAtLevel=1 + -Dcom.sun.management.jmxremote + -classpath + + ${exec.mainClass} + + + + + maven-surefire-plugin + 2.22.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + UTF-8 + + -parameters + + + + io.micronaut + micronaut-inject-java + 1.1.0 + + + io.micronaut + micronaut-validation + 1.1.0 + + + + + + test-compile + + testCompile + + + + -parameters + + + + io.micronaut + micronaut-inject-java + 1.1.0 + + + io.micronaut + micronaut-validation + 1.1.0 + + + + + + + + + + + diff --git a/appengine-java11/micronaut-helloworld/src/main/appengine/app.yaml b/appengine-java11/micronaut-helloworld/src/main/appengine/app.yaml new file mode 100644 index 00000000000..84aaf4d1967 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 diff --git a/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/Application.java b/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/Application.java new file mode 100644 index 00000000000..43aa33628a1 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/Application.java @@ -0,0 +1,26 @@ +/* + * Copyright 2019 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.appengine; + +import io.micronaut.runtime.Micronaut; + +public class Application { + + public static void main(String[] args) { + Micronaut.run(Application.class); + } +} diff --git a/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/HelloController.java b/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/HelloController.java new file mode 100644 index 00000000000..d68f870c0b0 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/HelloController.java @@ -0,0 +1,31 @@ +/* + * Copyright 2019 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.appengine; + +import io.micronaut.http.MediaType; +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; +import io.micronaut.http.annotation.Produces; + +@Controller("/") +public class HelloController { + @Get("/") + @Produces(MediaType.TEXT_PLAIN) + public String index() { + return "Hello World!"; + } +} diff --git a/appengine-java11/micronaut-helloworld/src/main/resources/application.yml b/appengine-java11/micronaut-helloworld/src/main/resources/application.yml new file mode 100644 index 00000000000..3d1d793550a --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/main/resources/application.yml @@ -0,0 +1,17 @@ +# Copyright 2019 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. + +micronaut: + application: + name: micronaut diff --git a/appengine-java11/micronaut-helloworld/src/main/resources/logback.xml b/appengine-java11/micronaut-helloworld/src/main/resources/logback.xml new file mode 100644 index 00000000000..ccafcd094ac --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/main/resources/logback.xml @@ -0,0 +1,28 @@ + + + + + + true + + + %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n + + + + + + + diff --git a/appengine-java11/micronaut-helloworld/src/test/java/com/example/appengine/HelloControllerTest.java b/appengine-java11/micronaut-helloworld/src/test/java/com/example/appengine/HelloControllerTest.java new file mode 100644 index 00000000000..619afa05640 --- /dev/null +++ b/appengine-java11/micronaut-helloworld/src/test/java/com/example/appengine/HelloControllerTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 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.appengine; + +import static org.junit.Assert.assertEquals; + +import io.micronaut.context.ApplicationContext; +import io.micronaut.http.HttpRequest; +import io.micronaut.http.client.HttpClient; +import io.micronaut.runtime.server.EmbeddedServer; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class HelloControllerTest { + private static EmbeddedServer server; + private static HttpClient client; + + @BeforeClass + public static void setupServer() { + + server = ApplicationContext.run(EmbeddedServer.class); + + client = server.getApplicationContext().createBean(HttpClient.class, server.getURL()); + } + + @AfterClass + public static void stopServer() { + if (client != null) { + client.stop(); + } + if (server != null) { + server.stop(); + } + } + + @Test + public void testHelloWorldResponse() { + String response = client.toBlocking().retrieve(HttpRequest.GET("/")); + assertEquals("Hello World!", response); + } +} diff --git a/appengine-java11/oauth2/README.md b/appengine-java11/oauth2/README.md new file mode 100644 index 00000000000..00d3c12c603 --- /dev/null +++ b/appengine-java11/oauth2/README.md @@ -0,0 +1,59 @@ +# Google OAuth 2.0 on Google App Engine Standard with Java 11 + +This sample shows how to implement an OAuth 2.0 flow using the +[Google OAuth Client Library for Java][client] to access protected data stored +on Google services. OAuth 2.0 is a standard specification for allowing end +users to securely authorize a client application to access protected +server-side resources. + +[client]: https://developers.google.com/api-client-library/java/google-api-java-client/oauth2 + +## Setup you Google Cloud Project + +- Make sure [`gcloud`](https://cloud.google.com/sdk/docs/) is installed and initialized: +``` + gcloud init +``` +- If this is the first time you are creating an App Engine project +``` + gcloud app create +``` + +## Setup the Sample App + +- Copy the sample apps to your local machine: +``` + git clone https://github.com/GoogleCloudPlatform/java-docs-samples +``` + +- Add the [appengine-simple-jetty-main](../README.md#appengine-simple-jetty-main) +Main class to your classpath: +``` + cd java-docs-samples/appengine-java11/appengine-simple-jetty-main + mvn install +``` +- In the [Cloud Developers Console](https://cloud.google.com/console) > +API Manager > Credentials, create a OAuth Client ID for a Web Application. +You will need to provide an authorized redirect URI +origin: `https://.appspot.com/oauth2callback`. + +- Replace `CLIENT_ID` and `CLIENT_SECRET` with these values in your +[app.yaml](/src/main/appengine/app.yaml) + +- Move into the `appengine-java11/oauth2` directory and compile the app: +``` + cd ../oauth2 + mvn package +``` + +## Deploy to App Engine Standard + +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml new file mode 100644 index 00000000000..6a1294d797c --- /dev/null +++ b/appengine-java11/oauth2/pom.xml @@ -0,0 +1,136 @@ + + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + oauth2-sample + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + + + + com.google.oauth-client + google-oauth-client + 1.29.0 + provided + + + + com.google.oauth-client + google-oauth-client-servlet + 1.29.0 + provided + + + + com.google.apis + google-api-services-oauth2 + v2-rev20190313-1.28.0 + provided + + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + jstl + jstl + 1.2 + provided + + + + + + oauth2 + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + oauth2 + + + + + org.eclipse.jetty + jetty-maven-plugin + 9.4.18.v20190429 + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + + + diff --git a/appengine-java11/oauth2/src/main/appengine/app.yaml b/appengine-java11/oauth2/src/main/appengine/app.yaml new file mode 100644 index 00000000000..72d7e6ffe74 --- /dev/null +++ b/appengine-java11/oauth2/src/main/appengine/app.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main oauth2.war' + +# [START gae_java11_oauth2_yaml] +env_variables: + CLIENT_ID: '' + CLIENT_SECRET: '' +# [END gae_java11_oauth2_yaml] diff --git a/appengine-java11/oauth2/src/main/java/com/example/appengine/LogoutServlet.java b/appengine-java11/oauth2/src/main/java/com/example/appengine/LogoutServlet.java new file mode 100644 index 00000000000..2f1fe74fc9a --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/LogoutServlet.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 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.appengine; + +import java.io.IOException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@SuppressWarnings("serial") +@WebServlet(urlPatterns = "/logout") +public class LogoutServlet extends HttpServlet { + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + req.getSession().invalidate(); + resp.sendRedirect("/"); + } +} diff --git a/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java new file mode 100644 index 00000000000..2312f4cf438 --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java @@ -0,0 +1,53 @@ +/* + * Copyright 2019 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.appengine; + +// [START gae_java11_oauth2_login] +import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; +import com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeServlet; +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@SuppressWarnings("serial") +@WebServlet(urlPatterns = "/login") +public class Oauth2AuthorizationCodeServlet extends AbstractAuthorizationCodeServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + resp.sendRedirect("/"); + } + + @Override + protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { + return Utils.getRedirectUri(req); + } + + @Override + protected AuthorizationCodeFlow initializeFlow() throws IOException { + return Utils.newFlow(); + } + + @Override + protected String getUserId(HttpServletRequest req) throws ServletException, IOException { + return Utils.getUserId(req); + } +} +// [START gae_java11_oauth2_login] diff --git a/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java new file mode 100644 index 00000000000..bb17aad853c --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java @@ -0,0 +1,79 @@ +/* + * Copyright 2019 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.appengine; + +// [START gae_java11_oauth2_callback] +import com.google.api.client.auth.oauth2.AuthorizationCodeFlow; +import com.google.api.client.auth.oauth2.AuthorizationCodeResponseUrl; +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.extensions.servlet.auth.oauth2.AbstractAuthorizationCodeCallbackServlet; +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * This servlet class extends AbstractAuthorizationCodeServlet which if the end-user credentials are + * not found, will redirect the end-user to an authorization page. + */ +@SuppressWarnings("serial") +@WebServlet(urlPatterns = "/oauth2callback/*") +public class Oauth2CallbackServlet extends AbstractAuthorizationCodeCallbackServlet { + + /** Handles a successfully granted authorization. */ + @Override + protected void onSuccess(HttpServletRequest req, HttpServletResponse resp, Credential credential) + throws ServletException, IOException { + resp.sendRedirect("/"); + } + + /** Handles an error to the authorization, such as when an end user denies authorization. */ + @Override + protected void onError( + HttpServletRequest req, HttpServletResponse resp, AuthorizationCodeResponseUrl errorResponse) + throws ServletException, IOException { + resp.getWriter().print("

You Denied Authorization.

"); + resp.setStatus(200); + resp.addHeader("Content-Type", "text/html"); + } + + /** Returns the redirect URI for the given HTTP servlet request. */ + @Override + protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException { + return Utils.getRedirectUri(req); + } + + /** + * Loads the authorization code flow to be used across all HTTP servlet requests (only called + * during the first HTTP servlet request with an authorization code). + */ + @Override + protected AuthorizationCodeFlow initializeFlow() throws IOException { + return Utils.newFlow(); + } + + /** + * Returns the user ID for the given HTTP servlet request. This identifies your application's user + * and is used to assign and persist credentials to that user. + */ + @Override + protected String getUserId(HttpServletRequest req) throws ServletException, IOException { + return Utils.getUserId(req); + } +} +// [END gae_java11_oauth2_callback] diff --git a/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java b/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java new file mode 100644 index 00000000000..f261d1e583b --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java @@ -0,0 +1,108 @@ +/* + * Copyright 2019 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.appengine; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; +import com.google.api.client.http.GenericUrl; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.client.util.store.MemoryDataStoreFactory; +import com.google.api.services.oauth2.Oauth2; +import com.google.api.services.oauth2.model.Userinfoplus; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +public class Utils { + + /** Get application name from the runtime environment variable */ + static final String APP_NAME = System.getenv("GAE_APPLICATION"); + + /** + * Global instance of the {@link DataStoreFactory}. The best practice is to make it a single + * globally shared instance across your application. + */ + private static final MemoryDataStoreFactory DATA_STORE_FACTORY = + MemoryDataStoreFactory.getDefaultInstance(); + + /** Global instance of the HTTP transport. */ + static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + /** Global instance of the JSON factory. */ + static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance(); + + /** Set your OAuth 2.0 Client Credentials */ + private static String CLIENT_ID = System.getenv("CLIENT_ID"); + + private static String CLIENT_SECRET = System.getenv("CLIENT_SECRET"); + + /** Scopes for requesting access to Google OAuth2 API */ + private static final List SCOPES = + Arrays.asList( + "https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email"); + + /** Returns the redirect URI for the given HTTP servlet request. */ + static String getRedirectUri(HttpServletRequest req) { + GenericUrl url = new GenericUrl(req.getRequestURL().toString()); + url.setRawPath("/oauth2callback"); + return url.build(); + } + + // [START gae_java11_oauth2_code_flow] + /** + * Loads the authorization code flow to be used across all HTTP servlet requests. It is only + * called during the first HTTP servlet request. + */ + public static GoogleAuthorizationCodeFlow newFlow() throws IOException { + return new GoogleAuthorizationCodeFlow.Builder( + HTTP_TRANSPORT, JSON_FACTORY, CLIENT_ID, CLIENT_SECRET, SCOPES) + .setDataStoreFactory(DATA_STORE_FACTORY) + .setAccessType("offline") + .build(); + } + // [END gae_java11_oauth2_code_flow] + + /** + * Returns the user ID for the given HTTP servlet request. This identifies your application's user + * and is used to assign and persist credentials to that user. Most commonly, this will be a user + * id stored in the session or even the session id itself. + */ + static String getUserId(HttpServletRequest req) throws ServletException, IOException { + return req.getSession().getId(); + } + + // [START gae_java11_oauth2_get_user] + /** Obtain end-user authorization grant for Google APIs and return username */ + public static String getUserInfo(Credential credential) throws IOException { + Oauth2 oauth2Client = + new Oauth2.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) + .setApplicationName(APP_NAME) + .build(); + + // Retrieve user profile + Userinfoplus userInfo = oauth2Client.userinfo().get().execute(); + String username = userInfo.getGivenName(); + return username; + } + // [END gae_java11_oauth2_get_user] +} diff --git a/appengine-java11/oauth2/src/main/webapp/WEB-INF/web.xml b/appengine-java11/oauth2/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..9bbe828bfd4 --- /dev/null +++ b/appengine-java11/oauth2/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,27 @@ + + + + + + index.jsp + + + diff --git a/appengine-java11/oauth2/src/main/webapp/index.jsp b/appengine-java11/oauth2/src/main/webapp/index.jsp new file mode 100644 index 00000000000..c4340770761 --- /dev/null +++ b/appengine-java11/oauth2/src/main/webapp/index.jsp @@ -0,0 +1,52 @@ + + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ page import="com.example.appengine.Utils" %> +<%@ page import="com.google.api.client.auth.oauth2.Credential" %> + + + + + + title + + +<% + String userId = request.getSession().getId(); + // Use the session id to retrieve access token. + Credential credential = Utils.newFlow().loadCredential(userId); + + if (credential == null) { +%> + Sign In with Google +<% + } else { + // Use the credentials to get user info from the OAuth2.0 API. + String username = Utils.getUserInfo(credential); +%> +

Hello, <%= username %>!

+ +
+ +
+<% + } +%> + + diff --git a/appengine-java11/oauth2/src/main/webapp/stylesheets/main.css b/appengine-java11/oauth2/src/main/webapp/stylesheets/main.css new file mode 100644 index 00000000000..749e6a4476f --- /dev/null +++ b/appengine-java11/oauth2/src/main/webapp/stylesheets/main.css @@ -0,0 +1,20 @@ +/* + Copyright 2019 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. +*/ + +body { + font-family: Roboto, Helvetica, sans-serif; + color: #4285F4; +} diff --git a/appengine-java11/quarkus-helloworld/README.md b/appengine-java11/quarkus-helloworld/README.md new file mode 100644 index 00000000000..facd1c43536 --- /dev/null +++ b/appengine-java11/quarkus-helloworld/README.md @@ -0,0 +1,20 @@ +# Quarkus Application on Google App Engine Standard with Java 11 + +This sample shows how to deploy a [Quarkus](https://quarkus.io/) +application to Google App Engine standard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/quarkus-helloworld/pom.xml b/appengine-java11/quarkus-helloworld/pom.xml new file mode 100644 index 00000000000..dd84fe268cb --- /dev/null +++ b/appengine-java11/quarkus-helloworld/pom.xml @@ -0,0 +1,109 @@ + + + + 4.0.0 + com.example.appengine.quarkus + quarkus-helloworld + 1.0-SNAPSHOT + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + UTF-8 + + + + + + io.quarkus + quarkus-bom + 0.11.0 + pom + import + + + + + + + io.quarkus + quarkus-resteasy + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-junit5 + + + io.rest-assured + rest-assured + test + + + + + + + io.quarkus + quarkus-maven-plugin + 0.11.0 + + + + build + + + + + + ${project.build.directory}/appengine-staging/lib + ${project.build.directory}/appengine-staging/${build.finalName} + + + + + maven-surefire-plugin + 2.22.0 + + + org.jboss.logmanager.LogManager + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + quarkus-helloworld + + + + + diff --git a/appengine-java11/quarkus-helloworld/src/main/appengine/app.yaml b/appengine-java11/quarkus-helloworld/src/main/appengine/app.yaml new file mode 100644 index 00000000000..36aa727f2db --- /dev/null +++ b/appengine-java11/quarkus-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,19 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F1 +# The entrypoint here is mandatory as the appengine-staging area contains an +# exploded fatjar. +entrypoint: 'java -XX:MaxRAM=128m -XX:ActiveProcessorCount=2 -Xmx32m -Dquarkus.log.file.enable=false -Dquarkus.http.host=0.0.0.0 -jar quarkus-helloworld-1.0-SNAPSHOT-runner.jar' diff --git a/appengine-java11/quarkus-helloworld/src/main/java/com/example/appengine/quarkus/HelloResource.java b/appengine-java11/quarkus-helloworld/src/main/java/com/example/appengine/quarkus/HelloResource.java new file mode 100644 index 00000000000..f2f11ac69b8 --- /dev/null +++ b/appengine-java11/quarkus-helloworld/src/main/java/com/example/appengine/quarkus/HelloResource.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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.appengine.quarkus; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "Hello World!"; + } +} diff --git a/appengine-java11/quarkus-helloworld/src/main/resources/META-INF/microprofile-config.properties b/appengine-java11/quarkus-helloworld/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 00000000000..b2fb315907f --- /dev/null +++ b/appengine-java11/quarkus-helloworld/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,13 @@ +# Copyright 2019 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. diff --git a/appengine-java11/quarkus-helloworld/src/test/java/com/example/appengine/quarkus/HelloResourceTest.java b/appengine-java11/quarkus-helloworld/src/test/java/com/example/appengine/quarkus/HelloResourceTest.java new file mode 100644 index 00000000000..42f0a78f1ad --- /dev/null +++ b/appengine-java11/quarkus-helloworld/src/test/java/com/example/appengine/quarkus/HelloResourceTest.java @@ -0,0 +1,32 @@ +/* + * Copyright 2019 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.appengine.quarkus; + +import static io.restassured.RestAssured.given; +import static org.hamcrest.CoreMatchers.is; + +import io.quarkus.test.junit.QuarkusTest; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class HelloResourceTest { + + @Test + public void testHelloEndpoint() { + given().when().get("/").then().statusCode(200).body(is("Hello World!")); + } +} diff --git a/appengine-java11/spanner/README.md b/appengine-java11/spanner/README.md new file mode 100644 index 00000000000..9e28e213349 --- /dev/null +++ b/appengine-java11/spanner/README.md @@ -0,0 +1,60 @@ +# Google Cloud Spanner Sample + + +Open in Cloud Shell + +This sample demonstrates how to use [Google Cloud Spanner][spanner-docs] +from [Google App Engine standard Java 11 environment][ae-docs]. + +[spanner-docs]: https://cloud.google.com/spanner/docs/ +[ae-docs]: https://cloud.google.com/appengine/docs/java/ + + +## Setup your Google Cloud Platform Project +- Install the [Google Cloud SDK](https://cloud.google.com/sdk/) and run: +``` + gcloud init +``` +If this is your first time creating an App engine application: +``` + gcloud app create +``` + +## Setup the Sample App + +- Copy the sample apps to your local machine: +``` + git clone https://github.com/GoogleCloudPlatform/java-docs-samples +``` + +- Add the [appengine-simple-jetty-main](../README.md#appengine-simple-jetty-main) +Main class to your classpath: +``` + cd java-docs-samples/appengine-java11/appengine-simple-jetty-main + mvn install +``` + +- [Create a Spanner instance](https://cloud.google.com/spanner/docs/quickstart-console#create_an_instance). + +- Update `SPANNER_INSTANCE` value in `[app.yaml](src/main/appengine/app.yaml)` with your instance id. + +- Move into the `appengine-java11/spanner` directory and compile the app: +``` + cd ../spanner + mvn package +``` + +## Endpoints +- `/spanner` : will run sample operations against the spanner instance in order. Individual tasks can be run +using the `task` query parameter. See [SpannerTasks](src/main/java/com/example/appengine/spanner/SpannerTasks.java) +for supported set of tasks. +Note : by default all the spanner example operations run in order, this operation may take a while to return. + +## Deploying +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To see the results of the deployed sample application, open +`https://PROJECT_ID.appspot.com/spanner` in a web browser. +Note : by default all the spanner example operations run in order, this operation may take a while to show results. diff --git a/appengine-java11/spanner/pom.xml b/appengine-java11/spanner/pom.xml new file mode 100644 index 00000000000..9f21fb38ce0 --- /dev/null +++ b/appengine-java11/spanner/pom.xml @@ -0,0 +1,107 @@ + + + + com.example.appengine + 4.0.0 + appengine-spanner-j11 + 1.0-SNAPSHOT + war + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + + + com.example.appengine.demo + simple-jetty-main + 1 + provided + + + + com.google.cloud + google-cloud-spanner + 1.7.0 + provided + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + spanner + + + org.apache.maven.plugins + maven-war-plugin + 3.2.2 + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + copy + prepare-package + + copy-dependencies + + + + ${project.build.directory}/appengine-staging + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + spanner + + + + + diff --git a/appengine-java11/spanner/src/main/appengine/app.yaml b/appengine-java11/spanner/src/main/appengine/app.yaml new file mode 100644 index 00000000000..ef5374484bb --- /dev/null +++ b/appengine-java11/spanner/src/main/appengine/app.yaml @@ -0,0 +1,19 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main spanner.war' +env_variables: + SPANNER_INSTANCE: diff --git a/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerClient.java b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerClient.java new file mode 100644 index 00000000000..2a0f4d86983 --- /dev/null +++ b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerClient.java @@ -0,0 +1,134 @@ +/* + * Copyright 2019 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.appengine.spanner; + +import com.google.cloud.spanner.DatabaseAdminClient; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.DatabaseId; +import com.google.cloud.spanner.Spanner; +import com.google.cloud.spanner.SpannerOptions; +import java.io.IOException; +import java.util.UUID; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.annotation.WebListener; + +// With @WebListener annotation the webapp/WEB-INF/web.xml is no longer required. +@WebListener +public class SpannerClient implements ServletContextListener { + + private static String PROJECT_ID; + private static String INSTANCE_ID; + private static String DATABASE_ID; + + // The initial connection can be an expensive operation -- We cache this Connection + // to speed things up. For this sample, keeping them here is a good idea, for + // your application, you may wish to keep this somewhere else. + private static Spanner spanner = null; + private static DatabaseAdminClient databaseAdminClient = null; + private static DatabaseClient databaseClient = null; + + private static ServletContext sc; + + private static void connect() throws IOException { + if (INSTANCE_ID == null) { + if (sc != null) { + sc.log("environment variable SPANNER_INSTANCE need to be defined."); + } + return; + } + SpannerOptions options = SpannerOptions.newBuilder().build(); + PROJECT_ID = options.getProjectId(); + spanner = options.getService(); + databaseAdminClient = spanner.getDatabaseAdminClient(); + } + + static DatabaseAdminClient getDatabaseAdminClient() { + if (databaseAdminClient == null) { + try { + connect(); + } catch (IOException e) { + if (sc != null) { + sc.log("getDatabaseAdminClient ", e); + } + } + } + if (databaseAdminClient == null) { + if (sc != null) { + sc.log("Spanner : Unable to connect"); + } + } + return databaseAdminClient; + } + + static DatabaseClient getDatabaseClient() { + if (databaseClient == null) { + databaseClient = + spanner.getDatabaseClient(DatabaseId.of(PROJECT_ID, INSTANCE_ID, DATABASE_ID)); + } + return databaseClient; + } + + @Override + public void contextInitialized(ServletContextEvent event) { + if (event != null) { + sc = event.getServletContext(); + if (INSTANCE_ID == null) { + INSTANCE_ID = sc.getInitParameter("SPANNER_INSTANCE"); + } + } + // try system properties + if (INSTANCE_ID == null) { + INSTANCE_ID = System.getProperty("SPANNER_INSTANCE"); + } + + if (DATABASE_ID == null) { + DATABASE_ID = "db-" + UUID.randomUUID().toString().substring(0, 25); + } + + try { + connect(); + } catch (IOException e) { + if (sc != null) { + sc.log("SpannerConnection - connect ", e); + } + } + if (databaseAdminClient == null) { + if (sc != null) { + sc.log("SpannerConnection - No Connection"); + } + } + if (sc != null) { + sc.log("ctx Initialized: " + INSTANCE_ID + " " + DATABASE_ID); + } + } + + @Override + public void contextDestroyed(ServletContextEvent servletContextEvent) { + // App Engine does not currently invoke this method. + databaseAdminClient = null; + } + + static String getInstanceId() { + return INSTANCE_ID; + } + + static String getDatabaseId() { + return DATABASE_ID; + } +} diff --git a/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasks.java b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasks.java new file mode 100644 index 00000000000..cca25f26173 --- /dev/null +++ b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasks.java @@ -0,0 +1,435 @@ +/* + * Copyright 2019 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.appengine.spanner; + +import com.google.cloud.spanner.Database; +import com.google.cloud.spanner.DatabaseClient; +import com.google.cloud.spanner.Key; +import com.google.cloud.spanner.KeySet; +import com.google.cloud.spanner.Mutation; +import com.google.cloud.spanner.ReadOnlyTransaction; +import com.google.cloud.spanner.ResultSet; +import com.google.cloud.spanner.Statement; +import com.google.cloud.spanner.Struct; +import com.google.common.base.Stopwatch; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +class SpannerTasks { + + enum Task { + createDatabase, + writeExampleData, + query, + read, + addMarketingBudget, + updateMarketingBudget, + queryMarketingBudget, + addIndex, + readUsingIndex, + queryUsingIndex, + addStoringIndex, + readStoringIndex, + writeTransaction, + readOnlyTransaction + } + + /** Class to contain singer sample data. */ + static class Singer { + + final long singerId; + final String firstName; + final String lastName; + + Singer(long singerId, String firstName, String lastName) { + this.singerId = singerId; + this.firstName = firstName; + this.lastName = lastName; + } + } + + /** Class to contain album sample data. */ + static class Album { + + final long singerId; + final long albumId; + final String albumTitle; + + Album(long singerId, long albumId, String albumTitle) { + this.singerId = singerId; + this.albumId = albumId; + this.albumTitle = albumTitle; + } + } + + private static final List SINGERS = + Arrays.asList( + new Singer(1, "Marc", "Richards"), + new Singer(2, "Catalina", "Smith"), + new Singer(3, "Alice", "Trentor"), + new Singer(4, "Lea", "Martin"), + new Singer(5, "David", "Lomond")); + + private static final List ALBUMS = + Arrays.asList( + new Album(1, 1, "Total Junk"), + new Album(1, 2, "Go, Go, Go"), + new Album(2, 1, "Green"), + new Album(2, 2, "Forever Hold Your Peace"), + new Album(2, 3, "Terrified")); + + private static DatabaseClient databaseClient = null; + + private static void createDatabase(PrintWriter pw) + throws InterruptedException, ExecutionException { + Iterable statements = + Arrays.asList( + "CREATE TABLE Singers (\n" + + " SingerId INT64 NOT NULL,\n" + + " FirstName STRING(1024),\n" + + " LastName STRING(1024),\n" + + " SingerInfo BYTES(MAX)\n" + + ") PRIMARY KEY (SingerId)", + "CREATE TABLE Albums (\n" + + " SingerId INT64 NOT NULL,\n" + + " AlbumId INT64 NOT NULL,\n" + + " AlbumTitle STRING(MAX)\n" + + ") PRIMARY KEY (SingerId, AlbumId),\n" + + " INTERLEAVE IN PARENT Singers ON DELETE CASCADE"); + Database db = + SpannerClient.getDatabaseAdminClient() + .createDatabase( + SpannerClient.getInstanceId(), SpannerClient.getDatabaseId(), statements) + .get(); + pw.println("Created database [" + db.getId() + "]"); + } + + private static void writeExampleData(PrintWriter pw) { + List mutations = new ArrayList<>(); + for (Singer singer : SINGERS) { + mutations.add( + Mutation.newInsertBuilder("Singers") + .set("SingerId") + .to(singer.singerId) + .set("FirstName") + .to(singer.firstName) + .set("LastName") + .to(singer.lastName) + .build()); + } + for (Album album : ALBUMS) { + mutations.add( + Mutation.newInsertBuilder("Albums") + .set("SingerId") + .to(album.singerId) + .set("AlbumId") + .to(album.albumId) + .set("AlbumTitle") + .to(album.albumTitle) + .build()); + } + SpannerClient.getDatabaseClient().write(mutations); + } + + private static void query(PrintWriter pw) { + // singleUse() can be used to execute a single read or query against Cloud Spanner. + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .executeQuery(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums")); + while (resultSet.next()) { + pw.printf("%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); + } + } + + private static void read(PrintWriter pw) { + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .read( + "Albums", + // KeySet.all() can be used to read all rows in a table. KeySet exposes other + // methods to read only a subset of the table. + KeySet.all(), + Arrays.asList("SingerId", "AlbumId", "AlbumTitle")); + while (resultSet.next()) { + pw.printf("%d %d %s\n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2)); + } + } + + private static void addMarketingBudgetColumnToAlbums(PrintWriter pw) + throws ExecutionException, InterruptedException { + SpannerClient.getDatabaseAdminClient() + .updateDatabaseDdl( + SpannerClient.getInstanceId(), + SpannerClient.getDatabaseId(), + Collections.singletonList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"), + null) + .get(); + } + + // Before executing this method, a new column MarketingBudget has to be added to the Albums + // table by applying the DDL statement "ALTER TABLE Albums ADD COLUMN MarketingBudget INT64". + private static void updateMarketingBudgetData() { + // Mutation can be used to update/insert/delete a single row in a table. Here we use + // newUpdateBuilder to create update mutations. + List mutations = + Arrays.asList( + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(1) + .set("AlbumId") + .to(1) + .set("MarketingBudget") + .to(100000) + .build(), + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(2) + .set("AlbumId") + .to(2) + .set("MarketingBudget") + .to(500000) + .build()); + // This writes all the mutations to Cloud Spanner atomically. + SpannerClient.getDatabaseClient().write(mutations); + } + + private static void writeWithTransaction() { + SpannerClient.getDatabaseClient() + .readWriteTransaction() + .run( + (transactionContext -> { + // Transfer marketing budget from one album to another. We do it in a transaction to + // ensure that the transfer is atomic. + Struct row = + transactionContext.readRow( + "Albums", Key.of(2, 2), Arrays.asList("MarketingBudget")); + long album2Budget = row.getLong(0); + // Transaction will only be committed if this condition still holds at the time of + // commit. Otherwise it will be aborted and the callable will be rerun by the + // client library. + if (album2Budget >= 300000) { + long album1Budget = + transactionContext + .readRow("Albums", Key.of(1, 1), Arrays.asList("MarketingBudget")) + .getLong(0); + long transfer = 200000; + album1Budget += transfer; + album2Budget -= transfer; + transactionContext.buffer( + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(1) + .set("AlbumId") + .to(1) + .set("MarketingBudget") + .to(album1Budget) + .build()); + transactionContext.buffer( + Mutation.newUpdateBuilder("Albums") + .set("SingerId") + .to(2) + .set("AlbumId") + .to(2) + .set("MarketingBudget") + .to(album2Budget) + .build()); + } + return null; + })); + } + + private static void queryMarketingBudget(PrintWriter pw) { + // Rows without an explicit value for MarketingBudget will have a MarketingBudget equal to + // null. + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .executeQuery(Statement.of("SELECT SingerId, AlbumId, MarketingBudget FROM Albums")); + while (resultSet.next()) { + pw.printf( + "%d %d %s\n", + resultSet.getLong("SingerId"), + resultSet.getLong("AlbumId"), + // We check that the value is non null. ResultSet getters can only be used to retrieve + // non null values. + resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); + } + } + + private static void addIndex() throws ExecutionException, InterruptedException { + SpannerClient.getDatabaseAdminClient() + .updateDatabaseDdl( + SpannerClient.getInstanceId(), + SpannerClient.getDatabaseId(), + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), + null) + .get(); + } + + // Before running this example, add the index AlbumsByAlbumTitle by applying the DDL statement + // "CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)". + private static void queryUsingIndex(PrintWriter pw) { + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .executeQuery( + // We use FORCE_INDEX hint to specify which index to use. For more details see + // https://cloud.google.com/spanner/docs/query-syntax#from-clause + Statement.of( + "SELECT AlbumId, AlbumTitle, MarketingBudget\n" + + "FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle}\n" + + "WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo'")); + while (resultSet.next()) { + pw.printf( + "%d %s %s\n", + resultSet.getLong("AlbumId"), + resultSet.getString("AlbumTitle"), + resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); + } + } + + private static void readUsingIndex(PrintWriter pw) { + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle")); + while (resultSet.next()) { + pw.printf("%d %s\n", resultSet.getLong(0), resultSet.getString(1)); + } + } + + private static void addStoringIndex() throws ExecutionException, InterruptedException { + SpannerClient.getDatabaseAdminClient() + .updateDatabaseDdl( + SpannerClient.getInstanceId(), + SpannerClient.getDatabaseId(), + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 " + + "ON Albums(AlbumTitle) STORING (MarketingBudget)"), + null) + .get(); + } + + // Before running this example, create a storing index AlbumsByAlbumTitle2 by applying the DDL + // statement "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget)". + private static void readStoringIndex(PrintWriter pw) { + // We can read MarketingBudget also from the index since it stores a copy of MarketingBudget. + ResultSet resultSet = + SpannerClient.getDatabaseClient() + .singleUse() + .readUsingIndex( + "Albums", + "AlbumsByAlbumTitle2", + KeySet.all(), + Arrays.asList("AlbumId", "AlbumTitle", "MarketingBudget")); + while (resultSet.next()) { + pw.printf( + "%d %s %s\n", + resultSet.getLong(0), + resultSet.getString(1), + resultSet.isNull("MarketingBudget") ? "NULL" : resultSet.getLong("MarketingBudget")); + } + } + + private static void readOnlyTransaction(PrintWriter pw) { + // ReadOnlyTransaction must be closed by calling close() on it to release resources held by it. + // We use a try-with-resource block to automatically do so. + try (ReadOnlyTransaction transaction = + SpannerClient.getDatabaseClient().readOnlyTransaction()) { + ResultSet queryResultSet = + transaction.executeQuery( + Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums")); + while (queryResultSet.next()) { + pw.printf( + "%d %d %s\n", + queryResultSet.getLong(0), queryResultSet.getLong(1), queryResultSet.getString(2)); + } + ResultSet readResultSet = + transaction.read( + "Albums", KeySet.all(), Arrays.asList("SingerId", "AlbumId", "AlbumTitle")); + while (readResultSet.next()) { + pw.printf( + "%d %d %s\n", + readResultSet.getLong(0), readResultSet.getLong(1), readResultSet.getString(2)); + } + } + } + + static void runTask(Task task, PrintWriter pw) throws ExecutionException, InterruptedException { + Stopwatch stopwatch = Stopwatch.createStarted(); + switch (task) { + case createDatabase: + createDatabase(pw); + break; + case writeExampleData: + writeExampleData(pw); + break; + case query: + query(pw); + break; + case read: + read(pw); + break; + case addMarketingBudget: + addMarketingBudgetColumnToAlbums(pw); + break; + case updateMarketingBudget: + updateMarketingBudgetData(); + break; + case queryMarketingBudget: + queryMarketingBudget(pw); + break; + case addIndex: + addIndex(); + break; + case readUsingIndex: + readUsingIndex(pw); + break; + case queryUsingIndex: + queryUsingIndex(pw); + break; + case addStoringIndex: + addStoringIndex(); + break; + case readStoringIndex: + readStoringIndex(pw); + break; + case readOnlyTransaction: + readOnlyTransaction(pw); + break; + case writeTransaction: + writeWithTransaction(); + break; + default: + break; + } + stopwatch.stop(); + pw.println(task + " in milliseconds : " + stopwatch.elapsed(TimeUnit.MILLISECONDS)); + pw.println("===================================================================="); + } +} diff --git a/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasksServlet.java b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasksServlet.java new file mode 100644 index 00000000000..1efe0a506f1 --- /dev/null +++ b/appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasksServlet.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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.appengine.spanner; + +import com.example.appengine.spanner.SpannerTasks.Task; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * Example code for using the Cloud Spanner API. This example demonstrates all the common operations + * that can be done on Cloud Spanner. These are: + * + *

+ * + *

    + *
  • Creating a Cloud Spanner database. + *
  • Writing, reading and executing SQL queries. + *
  • Writing data using a read-write transaction. + *
  • Using an index to read and execute SQL queries over data. + *
+ * + *

Individual tasks can be run using "tasks" query parameter. {@link SpannerTasks.Task} lists + * supported tasks. All tasks are run in order if no parameter or "tasks=all" is provided. + */ +// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required. +@WebServlet(value = "/spanner") +public class SpannerTasksServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text"); + PrintWriter pw = resp.getWriter(); + try { + String tasksParam = req.getParameter("tasks"); + List tasks; + if (tasksParam == null || tasksParam.equals("all")) { + // cycle through all operations in order + tasks = Arrays.asList(Task.values()); + } else { + String[] tasksStr = tasksParam.split(","); + tasks = Arrays.stream(tasksStr).map(Task::valueOf).collect(Collectors.toList()); + } + + for (Task task : tasks) { + SpannerTasks.runTask(task, pw); + } + } catch (Exception e) { + e.printStackTrace(pw); + pw.append(e.getMessage()); + resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/appengine-java11/sparkjava-helloworld/README.md b/appengine-java11/sparkjava-helloworld/README.md new file mode 100644 index 00000000000..c76adc4171e --- /dev/null +++ b/appengine-java11/sparkjava-helloworld/README.md @@ -0,0 +1,20 @@ +# SparkJava Application on Google App Engine Standard with Java 11 + +This sample shows how to deploy a [SparkJava](http://sparkjava.com) +application to Google App Engine standard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/sparkjava-helloworld/pom.xml b/appengine-java11/sparkjava-helloworld/pom.xml new file mode 100644 index 00000000000..7492298dbbb --- /dev/null +++ b/appengine-java11/sparkjava-helloworld/pom.xml @@ -0,0 +1,112 @@ + + + + 4.0.0 + com.example.appengine.sparkdemo + sparkjava-helloworld + 1.0 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + com.sparkjava + spark-core + 2.9.0 + + + junit + junit + 4.12 + test + + + com.despegar + spark-test + 1.1.8 + test + + + com.despegar + http-java-native-client + 1.0.4 + test + + + + + + maven-assembly-plugin + + + package + + single + + + + + + jar-with-dependencies + + + + com.example.appengine.sparkdemo.Main + + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + com.example.appengine.sparkdemo.Main + + -jar + ${app.stage.stagingDirectory}/sparkjava-helloworld-1.0-jar-with-dependencies.jar + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + ${project.build.directory}/sparkjava-helloworld-1.0-jar-with-dependencies.jar + sparkjava-helloworld + + + + + diff --git a/appengine-java11/sparkjava-helloworld/src/main/appengine/app.yaml b/appengine-java11/sparkjava-helloworld/src/main/appengine/app.yaml new file mode 100644 index 00000000000..84aaf4d1967 --- /dev/null +++ b/appengine-java11/sparkjava-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,16 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F2 diff --git a/appengine-java11/sparkjava-helloworld/src/main/java/com/example/appengine/sparkdemo/Main.java b/appengine-java11/sparkjava-helloworld/src/main/java/com/example/appengine/sparkdemo/Main.java new file mode 100644 index 00000000000..c57002227bf --- /dev/null +++ b/appengine-java11/sparkjava-helloworld/src/main/java/com/example/appengine/sparkdemo/Main.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 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.appengine.sparkdemo; + +import spark.Spark; + +public class Main { + + public static void main(String[] args) { + // Starts the webapp on localhost:8080. + Spark.port(8080); + Spark.get("/", (req, res) -> "Hello World!"); + } +} diff --git a/appengine-java11/springboot-helloworld/README.md b/appengine-java11/springboot-helloworld/README.md new file mode 100644 index 00000000000..a466d9a13e1 --- /dev/null +++ b/appengine-java11/springboot-helloworld/README.md @@ -0,0 +1,20 @@ +# Spring Boot Application Google App Engine Standard with Java 11 + +This sample shows how to deploy a [Spring Boot](https://spring.io/projects/spring-boot) +application to Google App Engine stadndard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml new file mode 100644 index 00000000000..f14f5696bad --- /dev/null +++ b/appengine-java11/springboot-helloworld/pom.xml @@ -0,0 +1,103 @@ + + + + 4.0.0 + com.example.appengine + springboot-helloworld-j11 + 0.0.1-SNAPSHOT + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + Greenwich.SR1 + pom + import + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-jetty + 2.1.4.RELEASE + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.4.RELEASE + + + + repackage + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + springboot-helloworld + + + + + + diff --git a/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml b/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml new file mode 100644 index 00000000000..f584d9c79f8 --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,22 @@ +# Copyright 2019 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. + +# [START gae_java11_helloworld_yaml] +runtime: java11 +instance_class: F2 + +# Explicitly set the memory limit and maximum heap size for the Spring Boot app +env_variables: + JAVA_TOOL_OPTIONS: "-XX:MaxRAM=256m -XX:ActiveProcessorCount=2 -Xmx32m" +# [END gae_java11_helloworld_yaml] diff --git a/appengine-java11/springboot-helloworld/src/main/java/com/example/appengine/springboot/SpringbootApplication.java b/appengine-java11/springboot-helloworld/src/main/java/com/example/appengine/springboot/SpringbootApplication.java new file mode 100644 index 00000000000..9a4726c8096 --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/main/java/com/example/appengine/springboot/SpringbootApplication.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 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.appengine.springboot; + +// [START gae_java11_helloworld] +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@SpringBootApplication +@RestController +public class SpringbootApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringbootApplication.class, args); + } + + @GetMapping("/") + public String hello() { + return "Hello world!"; + } + +} +// [END gae_java11_helloworld] diff --git a/appengine-java11/springboot-helloworld/src/main/resources/application.properties b/appengine-java11/springboot-helloworld/src/main/resources/application.properties new file mode 100644 index 00000000000..88fcbaa4554 --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/main/resources/application.properties @@ -0,0 +1,13 @@ +# Copyright 2019 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. diff --git a/appengine-java11/tasks-handler/Dockerfile b/appengine-java11/tasks-handler/Dockerfile new file mode 100644 index 00000000000..b076d6aaa0a --- /dev/null +++ b/appengine-java11/tasks-handler/Dockerfile @@ -0,0 +1,23 @@ + +# Use the official maven/Java 8 image to create a build artifact. +# https://hub.docker.com/_/maven +FROM maven:3.6-jdk-11 as builder + +# Copy local code to the container image. +WORKDIR /app +COPY pom.xml . +COPY src ./src + +# Build a release artifact. +RUN mvn package -DskipTests + +# Use the Official OpenJDK image for a lean production stage of our multi-stage build. +# https://hub.docker.com/_/openjdk +# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds +FROM openjdk:11-jre-slim + +# Copy the jar to the production image from the builder stage. +COPY --from=builder /app/target/task-handler-j11-*.jar /task-handler-j11.jar + +# Run the web service on container startup. +CMD ["java","-Djava.security.egd=file:/dev/./urandom","-Dserver.port=${PORT}","-jar","/task-handler-j11.jar"] diff --git a/appengine-java11/tasks-handler/README.md b/appengine-java11/tasks-handler/README.md new file mode 100644 index 00000000000..10709e32fb5 --- /dev/null +++ b/appengine-java11/tasks-handler/README.md @@ -0,0 +1,4 @@ +# Task Handler App for Google Cloud Tasks App Engine Queue Samples + +This is a companion application using Spring Boot to process Cloud Tasks requests. +See directory [`appengine-java11/tasks`](../tasks/README.md) for instructions. diff --git a/appengine-java11/tasks-handler/pom.xml b/appengine-java11/tasks-handler/pom.xml new file mode 100644 index 00000000000..048629e4c63 --- /dev/null +++ b/appengine-java11/tasks-handler/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + com.example.appengine + task-handler-j11 + 0.0.1-SNAPSHOT + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.4.RELEASE + pom + import + + + + org.springframework.cloud + spring-cloud-dependencies + Greenwich.SR1 + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter-web + 2.1.4.RELEASE + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + 2.1.4.RELEASE + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.1.4.RELEASE + + + + repackage + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + task-handler + + + + + + + diff --git a/appengine-java11/tasks-handler/src/main/appengine/app.yaml b/appengine-java11/tasks-handler/src/main/appengine/app.yaml new file mode 100644 index 00000000000..e7e49ecd9b8 --- /dev/null +++ b/appengine-java11/tasks-handler/src/main/appengine/app.yaml @@ -0,0 +1,23 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F4 + +# [START gae_java11_task_handler_secured] +handlers: +- url: /tasks/create + script: field required but not used + login: admin +# [END gae_java11_task_handler_secured] diff --git a/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/Application.java b/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/Application.java new file mode 100644 index 00000000000..166a752f54e --- /dev/null +++ b/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/Application.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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.appengine.taskhandler; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/TaskHandlerController.java b/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/TaskHandlerController.java new file mode 100644 index 00000000000..2038ba347cd --- /dev/null +++ b/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/TaskHandlerController.java @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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.appengine.taskhandler; + +// [START gae_java11_task_handler] +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TaskHandlerController { + + @RequestMapping( + value = "/tasks/create", + method = RequestMethod.POST, + consumes = "application/octet-stream") + @ResponseStatus(HttpStatus.OK) + public String taskHandler(@RequestBody String body) { + String output; + output = String.format("Received task with payload %s", body); + System.out.println(output); + + return output; + } +} +// [END gae_java11_task_handler] diff --git a/appengine-java11/tasks-handler/src/main/resources/application.properties b/appengine-java11/tasks-handler/src/main/resources/application.properties new file mode 100644 index 00000000000..dcb1eada0b6 --- /dev/null +++ b/appengine-java11/tasks-handler/src/main/resources/application.properties @@ -0,0 +1,13 @@ + # Copyright 2019 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. diff --git a/appengine-java11/tasks/README.md b/appengine-java11/tasks/README.md new file mode 100644 index 00000000000..5f8837790ab --- /dev/null +++ b/appengine-java11/tasks/README.md @@ -0,0 +1,98 @@ +# Google Cloud Tasks App Engine Queue Samples + +Sample command-line program for interacting with the Cloud Tasks API +using App Engine queues. + +App Engine queues push tasks to an App Engine HTTP target. This directory +contains both the App Engine app to deploy, as well as the snippets to run +locally to push tasks to it, which could also be called on App Engine. + +`CreateTask.java` is a simple command-line program to create +tasks to be pushed to the App Engine app. + +Directory `task-handler/` is the main App Engine app. This app serves as an endpoint to receive +App Engine task attempts. + + +## Initial Setup + + * Set up a Google Cloud Project and enable billing. + * Enable the + [Cloud Tasks API](https://console.cloud.google.com/launcher/details/google/cloudtasks.googleapis.com). + * Download and install the [Cloud SDK](https://cloud.google.com/sdk). + * Download and install [Maven](http://maven.apache.org/install.html). + * Set up [Google Application Credentials](https://cloud.google.com/docs/authentication/getting-started). + +## Creating a queue + +To create a queue using the Cloud SDK, use the following gcloud command: + +``` +gcloud beta tasks queues create my-appengine-queue +``` + +Note: A newly created queue will route to the default App Engine service and +version unless configured to do otherwise. + +## Deploying the App Engine app + +[Using Maven and the App Engine Plugin](https://cloud.google.com/appengine/docs/flexible/java/using-maven) +& [Maven Plugin Goals and Parameters](https://cloud.google.com/appengine/docs/flexible/java/maven-reference) + +- Copy the sample apps to your local machine: +``` +git clone https://github.com/GoogleCloudPlatform/java-docs-samples +``` + +- Move into the `task-handler` directory: +``` +cd java-docs-samples/appengine-java11/task-handler +``` + +- Deploy the app +``` +mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +## Run the Sample Using the Command Line + +- Move into the `appengine-java11/tasks` directory and compile the app: +``` +cd ../tasks +mvn package +``` + +Set environment variables: + +First, your project ID: + +``` +export GOOGLE_CLOUD_PROJECT="" +``` + +Then the queue ID, as specified at queue creation time. Queue IDs already +created can be listed with `gcloud beta tasks queues list`. + +``` +export QUEUE_ID="my-appengine-queue" +``` + +And finally the location ID, which can be discovered with +`gcloud beta tasks queues describe $QUEUE_ID`, with the location embedded in +the "name" value (for instance, if the name is +"projects/my-project/locations/us-central1/queues/my-appengine-queue", then the +location is "us-central1"). + +``` +export LOCATION_ID="us-central1" +``` + +Create a task, targeted at the `/tasks/create` endpoint, with a payload specified: + +``` +mvn exec:java -Dexec.mainClass="com.example.task.CreateTask" +``` + +The App Engine app serves as a target for the push requests. It has an +endpoint `/tasks/create` that reads the payload (i.e., the request body) of the +HTTP POST request and logs it. The log output can be viewed with [Stackdriver Logging](https://console.cloud.google.com/logs/viewer?minLogLevel=0). diff --git a/appengine-java11/tasks/pom.xml b/appengine-java11/tasks/pom.xml new file mode 100644 index 00000000000..8fb600bf8b7 --- /dev/null +++ b/appengine-java11/tasks/pom.xml @@ -0,0 +1,77 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + appengine-tasks-j11 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + + 11 + 11 + + + + + + + com.google.cloud + google-cloud-tasks + 0.87.0-beta + provided + + + + + + tasks + + + org.apache.maven.plugins + maven-war-plugin + 3.2.2 + + false + + + + + org.codehaus.mojo + exec-maven-plugin + 1.6.0 + + com.example.task.CreateTask + false + + + + + diff --git a/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java b/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java new file mode 100644 index 00000000000..05fcda4eecc --- /dev/null +++ b/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java @@ -0,0 +1,67 @@ +/* + * Copyright 2019 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.task; + +// [START gae_java11_create_task] +import com.google.cloud.tasks.v2.AppEngineHttpRequest; +import com.google.cloud.tasks.v2.CloudTasksClient; +import com.google.cloud.tasks.v2.HttpMethod; +import com.google.cloud.tasks.v2.QueueName; +import com.google.cloud.tasks.v2.Task; +import com.google.protobuf.ByteString; +import com.google.protobuf.Timestamp; +import java.nio.charset.Charset; +import java.time.Clock; +import java.time.Instant; + +public class CreateTask { + public static void main(String[] args) throws Exception { + // Instantiates a client. + try (CloudTasksClient client = CloudTasksClient.create()) { + // Variables provided by system variables. + String projectId = System.getenv("PROJECT_ID"); + String queueName = System.getenv("QUEUE_ID"); + String location = System.getenv("LOCATION_ID"); + // Optional variables. + String payload = "hello"; + int seconds = 0; // Scheduled delay for the task in seconds + + // Construct the fully qualified queue name. + String queuePath = QueueName.of(projectId, location, queueName).toString(); + + // Construct the task body. + Task.Builder taskBuilder = + Task.newBuilder() + .setAppEngineHttpRequest( + AppEngineHttpRequest.newBuilder() + .setBody(ByteString.copyFrom(payload, Charset.defaultCharset())) + .setRelativeUri("/tasks/create") + .setHttpMethod(HttpMethod.POST) + .build()); + + // Add the scheduled time to the request. + taskBuilder.setScheduleTime( + Timestamp.newBuilder() + .setSeconds(Instant.now(Clock.systemUTC()).plusSeconds(seconds).getEpochSecond())); + + // Send create task request. + Task task = client.createTask(queuePath, taskBuilder.build()); + System.out.println("Task created: " + task.getName()); + } + } +} +// [END gae_java11_create_task] diff --git a/appengine-java11/vertx-helloworld/README.md b/appengine-java11/vertx-helloworld/README.md new file mode 100644 index 00000000000..6f3d1dac3d4 --- /dev/null +++ b/appengine-java11/vertx-helloworld/README.md @@ -0,0 +1,54 @@ +# Vert.x Application on Google App Engine Standard with Java 11 + +This sample shows how to deploy a [Vert.x](https://vertx.io/) +application to Google App Engine stadndard. + +## Setup + +See [Prerequisites](../README.md#Prerequisites). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +## See the application page +Navigate to `https://.appspot.com`. + +## The application + +The application is written to use Eclipse Vert.x to demonstrate the use of [Vert.x Web](https://vertx.io/docs/vertx-web/java/) as web server +and [Vert.x Web client](https://vertx.io/docs/vertx-web-client/java/). + +Vert.x is a fully non-blocking toolkit and some parts of the application use callbacks. + +The [main](src/main/java/com/google/appengine/vertxhello/Main.java) class creates the Vert.x instance deploys the `Server` class: + +``` +Vertx vertx = Vertx.vertx(); +vertx.deployVerticle(new Server()); +``` + +## The application + +When the [application](src/main/java/com/google/appengine/vertxhello/Application.java) starts + +- it creates a Vert.x Web client for querying the Google metadata API for the project ID displayed in the response +- it creates a Vert.x Web router when it starts and initializes it to serve all the routes with the `handleDefault` method +- it starts an HTTP server on the port `8080` + +``` +webClient = WebClient.create(vertx); + +Router router = Router.router(vertx); + +router.route().handler(this::handleDefault); + +vertx.createHttpServer() + .requestHandler(router) + .listen(8080, ar -> startFuture.handle(ar.mapEmpty())); +``` + +HTTP requests are served by the `handleDefault` method. This method uses the `WebClient` to query the Google metadata API +for the project ID and returns an _Hello World_ string that contains the project ID name. diff --git a/appengine-java11/vertx-helloworld/pom.xml b/appengine-java11/vertx-helloworld/pom.xml new file mode 100644 index 00000000000..c5637c6d94a --- /dev/null +++ b/appengine-java11/vertx-helloworld/pom.xml @@ -0,0 +1,108 @@ + + + + 4.0.0 + com.google.appengine.vertxdemo + vertx-hello-j11 + 1.0 + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 11 + 11 + + + + + io.vertx + vertx-core + 3.6.3 + + + io.vertx + vertx-web + 3.6.3 + + + io.vertx + vertx-web-client + 3.6.3 + + + + org.slf4j + slf4j-simple + 1.7.22 + jar + + + junit + junit + 4.12 + + + io.vertx + vertx-unit + 3.6.3 + + + + + + maven-assembly-plugin + + + package + + single + + + + + + jar-with-dependencies + + + + com.example.appengine.vertxhello.Main + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0 + + ${project.build.directory}/vertx-hello-j11-1.0-jar-with-dependencies.jar + vertx-hello-java11 + + + + + diff --git a/appengine-java11/vertx-helloworld/src/main/appengine/app.yaml b/appengine-java11/vertx-helloworld/src/main/appengine/app.yaml new file mode 100644 index 00000000000..5921aaa7d18 --- /dev/null +++ b/appengine-java11/vertx-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +runtime: java11 +instance_class: F4 +# The entry point is necessary to tell Vert.x where to store cached resources extracted from fat jars +entrypoint: 'java -Dvertx.cacheDirBase=/tmp -jar vertx-hello-j11-1.0-jar-with-dependencies.jar ' diff --git a/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Application.java b/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Application.java new file mode 100644 index 00000000000..d5ed5b45c7a --- /dev/null +++ b/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Application.java @@ -0,0 +1,64 @@ +/* + * Copyright 2019 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.appengine.vertxhello; + +import io.vertx.core.AbstractVerticle; +import io.vertx.core.Future; +import io.vertx.core.buffer.Buffer; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.client.HttpResponse; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.predicate.ResponsePredicate; + +public class Application extends AbstractVerticle { + + static String METADATA_HOST = "metadata.google.internal"; + static int METADATA_PORT = 80; + WebClient webClient; + + @Override + public void start(Future startFuture) { + webClient = WebClient.create(vertx); + Router router = Router.router(vertx); + router.route().handler(this::handleDefault); + + vertx + .createHttpServer() + .requestHandler(router) + .listen(8080, ar -> startFuture.handle(ar.mapEmpty())); + } + + private void handleDefault(RoutingContext routingContext) { + webClient + .get(METADATA_PORT, METADATA_HOST, "/computeMetadata/v1/project/project-id") + .putHeader("Metadata-Flavor", "Google") + .expect(ResponsePredicate.SC_OK) + .send( + res -> { + if (res.succeeded()) { + HttpResponse response = res.result(); + routingContext + .response() + .putHeader("content-type", "text/html") + .end("Hello World! from " + response.body()); + } else { + routingContext.fail(res.cause()); + } + }); + } +} diff --git a/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Main.java b/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Main.java new file mode 100644 index 00000000000..911f7dd2276 --- /dev/null +++ b/appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Main.java @@ -0,0 +1,28 @@ +/* + * Copyright 2019 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.appengine.vertxhello; + +import io.vertx.core.Vertx; + +public class Main { + + public static void main(String[] args) { + + Vertx vertx = Vertx.vertx(); + vertx.deployVerticle(new Application()); + } +} diff --git a/appengine-java11/vertx-helloworld/src/test/java/com/example/appengine/vertxhello/ApplicationTest.java b/appengine-java11/vertx-helloworld/src/test/java/com/example/appengine/vertxhello/ApplicationTest.java new file mode 100644 index 00000000000..3fcb6ea9f1d --- /dev/null +++ b/appengine-java11/vertx-helloworld/src/test/java/com/example/appengine/vertxhello/ApplicationTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2019 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.appengine.vertxhello; + +import io.vertx.core.Vertx; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; +import io.vertx.ext.web.client.WebClient; +import io.vertx.ext.web.client.predicate.ResponsePredicate; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(VertxUnitRunner.class) +public class ApplicationTest { + + private static Vertx vertx; + + @BeforeClass + public static void setUp(TestContext ctx) { + vertx = Vertx.vertx(); + startMetadataServer(ctx); + vertx.deployVerticle(new Application(), ctx.asyncAssertSuccess()); + } + + // Start a mock metadata server + private static void startMetadataServer(TestContext ctx) { + Application.METADATA_HOST = "localhost"; + Application.METADATA_PORT = 8081; + vertx + .createHttpServer() + .requestHandler( + req -> { + req.response().end("this-is-your-project"); + }) + .listen(8081, ctx.asyncAssertSuccess()); + } + + @AfterClass + public static void tearDown(TestContext ctx) { + vertx.close(ctx.asyncAssertSuccess()); + } + + @Test + public void test(TestContext ctx) { + WebClient client = WebClient.create(vertx); + client + .get(8080, "localhost", "/") + .expect(ResponsePredicate.SC_OK) + .send( + ctx.asyncAssertSuccess( + response -> { + ctx.assertEquals( + "Hello World! from this-is-your-project", response.bodyAsString()); + })); + } +} diff --git a/appengine-java8/analytics/pom.xml b/appengine-java8/analytics/pom.xml index faa0d2f4feb..2c2a7998e7b 100644 --- a/appengine-java8/analytics/pom.xml +++ b/appengine-java8/analytics/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/appidentity/pom.xml b/appengine-java8/appidentity/pom.xml index 307c6ce3a29..ab02db5f3b7 100644 --- a/appengine-java8/appidentity/pom.xml +++ b/appengine-java8/appidentity/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/bigquery/pom.xml b/appengine-java8/bigquery/pom.xml index b6f9969e856..9fd9e3650c5 100644 --- a/appengine-java8/bigquery/pom.xml +++ b/appengine-java8/bigquery/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/bigtable/pom.xml b/appengine-java8/bigtable/pom.xml index a84f217f864..b670b0ff16c 100644 --- a/appengine-java8/bigtable/pom.xml +++ b/appengine-java8/bigtable/pom.xml @@ -30,7 +30,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -139,7 +139,7 @@ limitations under the License. org.apache.maven.plugins maven-failsafe-plugin - 2.20.1 + 3.0.0-M3 ${bigtable.projectID} diff --git a/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelloWorld.java b/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelloWorld.java index d09dd80ec8d..1c0abe406af 100644 --- a/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelloWorld.java +++ b/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelloWorld.java @@ -30,7 +30,7 @@ import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.Table; import org.apache.hadoop.hbase.util.Bytes; -// [START example] +// [START bigtable_app_engine_standard_hw] /** * A minimal application that connects to Cloud Bigtable using the native HBase API and performs @@ -63,7 +63,6 @@ public static String create(Connection connection) { descriptor.addFamily(new HColumnDescriptor(COLUMN_FAMILY_NAME)); admin.createTable(descriptor); - // [END creating_a_table] } catch (IOException e) { return "Table exists."; } @@ -110,7 +109,7 @@ public static String doHelloWorld() { Result getResult = table.get(new Get(Bytes.toBytes(rowKey))); String greeting = Bytes.toString(getResult.getValue(COLUMN_FAMILY_NAME, COLUMN_NAME)); result.append("Get a single greeting by row key
"); - // [END getting_a_row] + result.append(" "); result.append(rowKey); result.append("= "); @@ -138,4 +137,4 @@ public static String doHelloWorld() { return result.toString(); } } -// [END example] +// [END bigtable_app_engine_standard_hw] diff --git a/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelper.java b/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelper.java index 81bbeb559d4..3b5cce5e4b1 100644 --- a/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelper.java +++ b/appengine-java8/bigtable/src/main/java/com/example/bigtable/BigtableHelper.java @@ -100,10 +100,10 @@ public void contextInitialized(ServletContextEvent event) { } if (PROJECT_ID == null) { - PROJECT_ID = System.getProperty("BIGTABLE_PROJECT"); + PROJECT_ID = System.getProperty("bigtable.projectID"); } if (INSTANCE_ID == null) { - INSTANCE_ID = System.getProperty("BIGTABLE_INSTANCE"); + INSTANCE_ID = System.getProperty("bigtable.instanceID"); } try { diff --git a/appengine-java8/bigtable/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/bigtable/src/main/webapp/WEB-INF/appengine-web.xml index 7cf89ffef4b..7b483e2c578 100644 --- a/appengine-java8/bigtable/src/main/webapp/WEB-INF/appengine-web.xml +++ b/appengine-java8/bigtable/src/main/webapp/WEB-INF/appengine-web.xml @@ -11,7 +11,6 @@ See the License for the specific language governing permissions and limitations under the License. --> - true java8 @@ -22,4 +21,3 @@ - diff --git a/appengine-java8/bigtable/src/test/java/com/example/bigtable/ITBigtableHelloWorld.java b/appengine-java8/bigtable/src/test/java/com/example/bigtable/BigtableHelloWorldTests.java similarity index 93% rename from appengine-java8/bigtable/src/test/java/com/example/bigtable/ITBigtableHelloWorld.java rename to appengine-java8/bigtable/src/test/java/com/example/bigtable/BigtableHelloWorldTests.java index 1b345b40655..5238d643c70 100644 --- a/appengine-java8/bigtable/src/test/java/com/example/bigtable/ITBigtableHelloWorld.java +++ b/appengine-java8/bigtable/src/test/java/com/example/bigtable/BigtableHelloWorldTests.java @@ -25,8 +25,7 @@ /** Unit tests for {@link BigtableHelloWorld}. */ @RunWith(JUnit4.class) -@SuppressWarnings("checkstyle:abbreviationaswordinname") -public class ITBigtableHelloWorld { +public class BigtableHelloWorldTests { private BigtableHelper helper; diff --git a/appengine-java8/cloudsql-postgres/pom.xml b/appengine-java8/cloudsql-postgres/pom.xml index 9ebd44c8929..8579e9e3f55 100644 --- a/appengine-java8/cloudsql-postgres/pom.xml +++ b/appengine-java8/cloudsql-postgres/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/cloudsql/pom.xml b/appengine-java8/cloudsql/pom.xml index 18c35f7d8da..9c541b9f49a 100644 --- a/appengine-java8/cloudsql/pom.xml +++ b/appengine-java8/cloudsql/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/datastore-indexes-exploding/pom.xml b/appengine-java8/datastore-indexes-exploding/pom.xml index b5153a454eb..ff5ad9a16c2 100644 --- a/appengine-java8/datastore-indexes-exploding/pom.xml +++ b/appengine-java8/datastore-indexes-exploding/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/datastore-indexes-perfect/pom.xml b/appengine-java8/datastore-indexes-perfect/pom.xml index 1060af67dd5..e3555a8b564 100644 --- a/appengine-java8/datastore-indexes-perfect/pom.xml +++ b/appengine-java8/datastore-indexes-perfect/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/datastore-indexes/pom.xml b/appengine-java8/datastore-indexes/pom.xml index ec0e869dbf9..1a5d0e9f337 100644 --- a/appengine-java8/datastore-indexes/pom.xml +++ b/appengine-java8/datastore-indexes/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/datastore-schedule-export/pom.xml b/appengine-java8/datastore-schedule-export/pom.xml index 9d8e2108c52..2f78ed5a3a7 100644 --- a/appengine-java8/datastore-schedule-export/pom.xml +++ b/appengine-java8/datastore-schedule-export/pom.xml @@ -10,7 +10,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/appengine-java8/datastore-schedule-export/src/main/webapp/WEB-INF/web.xml b/appengine-java8/datastore-schedule-export/src/main/webapp/WEB-INF/web.xml index 11ed2a032db..b70b5d9305f 100644 --- a/appengine-java8/datastore-schedule-export/src/main/webapp/WEB-INF/web.xml +++ b/appengine-java8/datastore-schedule-export/src/main/webapp/WEB-INF/web.xml @@ -6,4 +6,13 @@ index.jsp + + + export + /cloud-datastore-export + + + admin + + diff --git a/appengine-java8/datastore/pom.xml b/appengine-java8/datastore/pom.xml index a992e69b2ed..924f8c5cbec 100644 --- a/appengine-java8/datastore/pom.xml +++ b/appengine-java8/datastore/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/endpoints-v2-backend/pom.xml b/appengine-java8/endpoints-v2-backend/pom.xml index 0f8d6e4644d..8b486234d63 100644 --- a/appengine-java8/endpoints-v2-backend/pom.xml +++ b/appengine-java8/endpoints-v2-backend/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/endpoints-v2-guice/pom.xml b/appengine-java8/endpoints-v2-guice/pom.xml index ca2a1c152ac..a71d1926e0e 100644 --- a/appengine-java8/endpoints-v2-guice/pom.xml +++ b/appengine-java8/endpoints-v2-guice/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/endpoints-v2-migration/pom.xml b/appengine-java8/endpoints-v2-migration/pom.xml index ced00337dc7..bfc9c004505 100644 --- a/appengine-java8/endpoints-v2-migration/pom.xml +++ b/appengine-java8/endpoints-v2-migration/pom.xml @@ -29,7 +29,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/endpoints-v2-skeleton/pom.xml b/appengine-java8/endpoints-v2-skeleton/pom.xml index 4e6ab3e7c38..939e8fd2269 100644 --- a/appengine-java8/endpoints-v2-skeleton/pom.xml +++ b/appengine-java8/endpoints-v2-skeleton/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/firebase-event-proxy/pom.xml b/appengine-java8/firebase-event-proxy/pom.xml index 0deb19429a4..9157c775d94 100644 --- a/appengine-java8/firebase-event-proxy/pom.xml +++ b/appengine-java8/firebase-event-proxy/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/firebase-event-proxy/src/main/java/com/example/GaeFirebaseEventProxy/FirebaseEventProxy.java b/appengine-java8/firebase-event-proxy/src/main/java/com/example/GaeFirebaseEventProxy/FirebaseEventProxy.java index e4a203af34d..844a7f5aced 100644 --- a/appengine-java8/firebase-event-proxy/src/main/java/com/example/GaeFirebaseEventProxy/FirebaseEventProxy.java +++ b/appengine-java8/firebase-event-proxy/src/main/java/com/example/GaeFirebaseEventProxy/FirebaseEventProxy.java @@ -78,9 +78,6 @@ public void start() { public void onDataChange(DataSnapshot snapshot) { if (snapshot.exists()) { try { - // Convert value to JSON using Jackson - String json = new ObjectMapper().writeValueAsString(snapshot.getValue(false)); - // Replace the URL with the url of your own listener app. URL dest = new URL("http://gae-firebase-listener-python.appspot.com/log"); HttpURLConnection connection = (HttpURLConnection) dest.openConnection(); @@ -97,6 +94,9 @@ public void onDataChange(DataSnapshot snapshot) { connection.setRequestProperty("X-Appengine-Inbound-Appid", "dev-instance"); } + // Convert value to JSON using Jackson + String json = new ObjectMapper().writeValueAsString(snapshot.getValue(false)); + // Put Firebase data into http request StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("&fbSnapshot="); diff --git a/appengine-java8/firebase-tictactoe/pom.xml b/appengine-java8/firebase-tictactoe/pom.xml index a1ab0e1985a..779ebd723b7 100644 --- a/appengine-java8/firebase-tictactoe/pom.xml +++ b/appengine-java8/firebase-tictactoe/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/gaeinfo/pom.xml b/appengine-java8/gaeinfo/pom.xml index 49e7d4c0784..d96ca217d1d 100644 --- a/appengine-java8/gaeinfo/pom.xml +++ b/appengine-java8/gaeinfo/pom.xml @@ -28,7 +28,7 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/guestbook-cloud-datastore/pom.xml b/appengine-java8/guestbook-cloud-datastore/pom.xml index f0fd4402b23..2a98ddb646b 100644 --- a/appengine-java8/guestbook-cloud-datastore/pom.xml +++ b/appengine-java8/guestbook-cloud-datastore/pom.xml @@ -32,7 +32,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/guestbook-objectify/pom.xml b/appengine-java8/guestbook-objectify/pom.xml index 24061004dc3..10e832b574e 100644 --- a/appengine-java8/guestbook-objectify/pom.xml +++ b/appengine-java8/guestbook-objectify/pom.xml @@ -30,7 +30,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/images/pom.xml b/appengine-java8/images/pom.xml index 4b3b83b6710..874a70efa5f 100644 --- a/appengine-java8/images/pom.xml +++ b/appengine-java8/images/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/mail/pom.xml b/appengine-java8/mail/pom.xml index c62b15d96e5..5c4191186f3 100644 --- a/appengine-java8/mail/pom.xml +++ b/appengine-java8/mail/pom.xml @@ -27,7 +27,7 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/appengine-java8/mailgun/pom.xml b/appengine-java8/mailgun/pom.xml index b58a523d5f8..11eb09b484d 100644 --- a/appengine-java8/mailgun/pom.xml +++ b/appengine-java8/mailgun/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/mailgun/src/main/java/com/example/appengine/mailgun/MailgunServlet.java b/appengine-java8/mailgun/src/main/java/com/example/appengine/mailgun/MailgunServlet.java index 2928df1e361..de6ab8a15eb 100644 --- a/appengine-java8/mailgun/src/main/java/com/example/appengine/mailgun/MailgunServlet.java +++ b/appengine-java8/mailgun/src/main/java/com/example/appengine/mailgun/MailgunServlet.java @@ -75,8 +75,6 @@ private ClientResponse sendSimpleMessage(String recipient) { private ClientResponse sendComplexMessage(String recipient) { Client client = Client.create(); client.addFilter(new HTTPBasicAuthFilter("api", MAILGUN_API_KEY)); - WebResource webResource = - client.resource("https://api.mailgun.net/v3/" + MAILGUN_DOMAIN_NAME + "/messages"); FormDataMultiPart formData = new FormDataMultiPart(); formData.field("from", "Mailgun User "); formData.field("to", recipient); @@ -85,6 +83,8 @@ private ClientResponse sendComplexMessage(String recipient) { ClassLoader classLoader = getClass().getClassLoader(); File txtFile = new File(classLoader.getResource("example-attachment.txt").getFile()); formData.bodyPart(new FileDataBodyPart("attachment", txtFile, MediaType.TEXT_PLAIN_TYPE)); + WebResource webResource = + client.resource("https://api.mailgun.net/v3/" + MAILGUN_DOMAIN_NAME + "/messages"); return webResource .type(MediaType.MULTIPART_FORM_DATA_TYPE) .post(ClientResponse.class, formData); diff --git a/appengine-java8/mailjet/pom.xml b/appengine-java8/mailjet/pom.xml index b99ad10d3b7..857dc73fc91 100644 --- a/appengine-java8/mailjet/pom.xml +++ b/appengine-java8/mailjet/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/appengine-java8/memcache/pom.xml b/appengine-java8/memcache/pom.xml index f2da902bf26..fb1f74deb10 100644 --- a/appengine-java8/memcache/pom.xml +++ b/appengine-java8/memcache/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/metadata/pom.xml b/appengine-java8/metadata/pom.xml index 61a890ba6b9..fa009322809 100644 --- a/appengine-java8/metadata/pom.xml +++ b/appengine-java8/metadata/pom.xml @@ -28,7 +28,7 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/multitenancy/pom.xml b/appengine-java8/multitenancy/pom.xml index 8c8dc9660dd..5b234b02aac 100644 --- a/appengine-java8/multitenancy/pom.xml +++ b/appengine-java8/multitenancy/pom.xml @@ -30,7 +30,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/appengine-java8/oauth2/pom.xml b/appengine-java8/oauth2/pom.xml index 41f971381b1..8e26131b4b6 100644 --- a/appengine-java8/oauth2/pom.xml +++ b/appengine-java8/oauth2/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/appengine-java8/pom.xml b/appengine-java8/pom.xml deleted file mode 100644 index 28923429e79..00000000000 --- a/appengine-java8/pom.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - 4.0.0 - 1.0.0 - - com.google.cloud - appengine-java8-samples - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - 1.8 - 1.8 - - - - analytics - appidentity - bigquery - bigtable - cloudsql - cloudsql-postgres - datastore - datastore-indexes - datastore-indexes-exploding - datastore-indexes-perfect - endpoints-v2-backend - endpoints-v2-migration - endpoints-v2-guice - endpoints-v2-skeleton - firebase-event-proxy - firebase-tictactoe - gaeinfo - guestbook-cloud-datastore - guestbook-objectify - images - mail - mailgun - mailjet - memcache - metadata - multitenancy - oauth2 - pubsub - requests - remote-client - remote-server - search - sendgrid - spanner - static-files - taskqueues-deferred - taskqueues-pull - taskqueues-push - translate-pubsub - twilio - urlfetch - users - - - diff --git a/appengine-java8/pubsub/README.md b/appengine-java8/pubsub/README.md index c3294dcfb5e..b6c0aa16916 100644 --- a/appengine-java8/pubsub/README.md +++ b/appengine-java8/pubsub/README.md @@ -53,6 +53,21 @@ gcloud beta pubsub subscriptions create \ --ack-deadline 30 ``` +- Create a subscription for authenticated pushes to send messages to a Google Cloud Project URL such as https://.appspot.com/authenticated-push. + +The push auth service account must have Service Account Token Creator Role assigned, which can be done in the Cloud Console [IAM & admin](https://console.cloud.google.com/iam-admin/iam) UI. +`--push-auth-token-audience` is optional. If set, remember to modify the audience field check in [PubSubAuthenticatedPush.java](src/main/java/com/example/appengine/pubsub/PubSubAuthenticatedPush.java#L48). + +``` +gcloud beta pubsub subscriptions create \ + --topic \ + --push-endpoint \ + https://.appspot.com/pubsub/authenticated-push?token= \ + --ack-deadline 30 \ + --push-auth-service-account=[your-service-account-email] \ + --push-auth-token-audience=example.com +``` + ## Run locally Set the following environment variables and run using shown Maven command. You can then direct your browser to `http://localhost:8080/` @@ -70,6 +85,15 @@ mvn appengine:run "localhost:8080/pubsub/push?token=" ``` +### Authenticated push notifications + +Simulating authenticated push requests will fail because requests need to contain a Cloud Pub/Sub-generated JWT in the "Authorization" header. + +``` + curl -H "Content-Type: application/json" -i --data @sample_message.json + "localhost:8080/pubsub/authenticated-push?token=" +``` + ## Deploy Update the environment variables `PUBSUB_TOPIC` and `PUBSUB_VERIFICATION_TOKEN` in diff --git a/appengine-java8/pubsub/pom.xml b/appengine-java8/pubsub/pom.xml index 2d363d61075..efe2e68a02e 100644 --- a/appengine-java8/pubsub/pom.xml +++ b/appengine-java8/pubsub/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -47,6 +47,11 @@ jar provided + + com.googlecode.jatl + jatl + 0.2.2 + diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepository.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepository.java index c2fc2f78761..c4defa3b2da 100644 --- a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepository.java +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepository.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.example.appengine.pubsub; import java.util.List; @@ -26,8 +25,31 @@ public interface MessageRepository { /** * Retrieve most recent stored messages. + * * @param limit number of messages * @return list of messages */ List retrieve(int limit); + + /** Save claim to persistent storage. */ + void saveClaim(String claim); + + /** + * Retrieve most recent stored claims. + * + * @param limit number of messages + * @return list of claims + */ + List retrieveClaims(int limit); + + /** Save token to persistent storage. */ + void saveToken(String token); + + /** + * Retrieve most recent stored tokens. + * + * @param limit number of messages + * @return list of tokens + */ + List retrieveTokens(int limit); } diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepositoryImpl.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepositoryImpl.java index 521c82f13dd..85a66bdfc74 100644 --- a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepositoryImpl.java +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/MessageRepositoryImpl.java @@ -14,7 +14,6 @@ * limitations under the License. */ - package com.example.appengine.pubsub; import com.google.cloud.datastore.Datastore; @@ -35,6 +34,12 @@ public class MessageRepositoryImpl implements MessageRepository { private String messagesKind = "messages"; private KeyFactory keyFactory = getDatastoreInstance().newKeyFactory().setKind(messagesKind); + private String claimsKind = "claims"; + private KeyFactory claimsKindKeyFactory = + getDatastoreInstance().newKeyFactory().setKind(claimsKind); + private String tokensKind = "tokens"; + private KeyFactory tokensKindKeyFactory = + getDatastoreInstance().newKeyFactory().setKind(tokensKind); @Override public void save(Message message) { @@ -42,8 +47,8 @@ public void save(Message message) { Datastore datastore = getDatastoreInstance(); Key key = datastore.allocateId(keyFactory.newKey()); - Entity.Builder messageEntityBuilder = Entity.newBuilder(key) - .set("messageId", message.getMessageId()); + Entity.Builder messageEntityBuilder = + Entity.newBuilder(key).set("messageId", message.getMessageId()); if (message.getData() != null) { messageEntityBuilder = messageEntityBuilder.set("data", message.getData()); @@ -84,15 +89,72 @@ public List retrieve(int limit) { return messages; } + @Override + public void saveClaim(String claim) { + // Save message to "messages" + Datastore datastore = getDatastoreInstance(); + Key key = datastore.allocateId(claimsKindKeyFactory.newKey()); + + Entity.Builder claimEntityBuilder = Entity.newBuilder(key).set("claim", claim); + + datastore.put(claimEntityBuilder.build()); + } + + @Override + public List retrieveClaims(int limit) { + // Get claim saved in Datastore + Datastore datastore = getDatastoreInstance(); + Query query = Query.newEntityQueryBuilder().setKind(claimsKind).setLimit(limit).build(); + QueryResults results = datastore.run(query); + + List claims = new ArrayList<>(); + while (results.hasNext()) { + Entity entity = results.next(); + String claim = entity.getString("claim"); + if (claim != null) { + claims.add(claim); + } + } + return claims; + } + + @Override + public void saveToken(String token) { + // Save message to "messages" + Datastore datastore = getDatastoreInstance(); + Key key = datastore.allocateId(tokensKindKeyFactory.newKey()); + + Entity.Builder tokenEntityBuilder = Entity.newBuilder(key).set("token", token); + + datastore.put(tokenEntityBuilder.build()); + } + + @Override + public List retrieveTokens(int limit) { + // Get token saved in Datastore + Datastore datastore = getDatastoreInstance(); + Query query = Query.newEntityQueryBuilder().setKind(tokensKind).setLimit(limit).build(); + QueryResults results = datastore.run(query); + + List tokens = new ArrayList<>(); + while (results.hasNext()) { + Entity entity = results.next(); + String token = entity.getString("token"); + if (token != null) { + tokens.add(token); + } + } + return tokens; + } + private Datastore getDatastoreInstance() { return DatastoreOptions.getDefaultInstance().getService(); } - private MessageRepositoryImpl() { - } + private MessageRepositoryImpl() {} // retrieve a singleton instance - public static synchronized MessageRepositoryImpl getInstance() { + public static synchronized MessageRepositoryImpl getInstance() { if (instance == null) { instance = new MessageRepositoryImpl(); } diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubAuthenticatedPush.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubAuthenticatedPush.java new file mode 100644 index 00000000000..532bae32c95 --- /dev/null +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubAuthenticatedPush.java @@ -0,0 +1,112 @@ +/* + * Copyright 2019 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.appengine.pubsub; + +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.io.IOException; +import java.util.Base64; +import java.util.Collections; +import java.util.stream.Collectors; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START gae_standard_pubsub_auth_push] +@WebServlet(value = "/pubsub/authenticated-push") +public class PubSubAuthenticatedPush extends HttpServlet { + private final String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN"); + private final MessageRepository messageRepository; + private final GoogleIdTokenVerifier verifier = + new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory()) + /** + * Please change example.com to match with value you are providing while creating + * subscription as provided in @see README. + */ + .setAudience(Collections.singletonList("example.com")) + .build(); + private final Gson gson = new Gson(); + private final JsonParser jsonParser = new JsonParser(); + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) + throws IOException, ServletException { + + // Verify that the request originates from the application. + if (req.getParameter("token").compareTo(pubsubVerificationToken) != 0) { + resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + // Get the Cloud Pub/Sub-generated JWT in the "Authorization" header. + String authorizationHeader = req.getHeader("Authorization"); + if (authorizationHeader == null + || authorizationHeader.isEmpty() + || authorizationHeader.split(" ").length != 2) { + resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + String authorization = authorizationHeader.split(" ")[1]; + + try { + // Verify and decode the JWT. + GoogleIdToken idToken = verifier.verify(authorization); + messageRepository.saveToken(authorization); + messageRepository.saveClaim(idToken.getPayload().toPrettyString()); + // parse message object from "message" field in the request body json + // decode message data from base64 + Message message = getMessage(req); + messageRepository.save(message); + // 200, 201, 204, 102 status codes are interpreted as success by the Pub/Sub system + resp.setStatus(102); + super.doPost(req, resp); + } catch (Exception e) { + resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); + } + } + + private Message getMessage(HttpServletRequest request) throws IOException { + String requestBody = request.getReader().lines().collect(Collectors.joining("\n")); + JsonElement jsonRoot = jsonParser.parse(requestBody); + String messageStr = jsonRoot.getAsJsonObject().get("message").toString(); + Message message = gson.fromJson(messageStr, Message.class); + // decode from base64 + String decoded = decode(message.getData()); + message.setData(decoded); + return message; + } + + private String decode(String data) { + return new String(Base64.getDecoder().decode(data)); + } + + PubSubAuthenticatedPush(MessageRepository messageRepository) { + this.messageRepository = messageRepository; + } + + public PubSubAuthenticatedPush() { + this(MessageRepositoryImpl.getInstance()); + } +} +// [END gae_standard_pubsub_auth_push] diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubHome.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubHome.java index be9ab2546e6..105add23235 100644 --- a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubHome.java +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubHome.java @@ -16,6 +16,9 @@ package com.example.appengine.pubsub; +import com.googlecode.jatl.Html; +import java.io.StringWriter; +import java.io.Writer; import java.util.List; public class PubSubHome { @@ -28,22 +31,92 @@ public class PubSubHome { * * @return html representation of messages (one per row) */ - public static String getReceivedMessages() { + public static List getReceivedMessages() { List messageList = messageRepository.retrieve(MAX_MESSAGES); - return convertToHtmlTable(messageList); + return messageList; } - private static String convertToHtmlTable(List messages) { - StringBuilder sb = new StringBuilder(); - for (Message message : messages) { - sb.append(""); - sb.append("" + message.getMessageId() + ""); - sb.append("" + message.getData() + ""); - sb.append("" + message.getPublishTime() + ""); - sb.append(""); - } - return sb.toString(); + /** + * Retrieve received claims in html. + * + * @return html representation of claims (one per row) + */ + public static List getReceivedClaims() { + List claimList = messageRepository.retrieveClaims(MAX_MESSAGES); + return claimList; + } + + /** + * Retrieve received tokens in html. + * + * @return html representation of tokens (one per row) + */ + public static List getReceivedTokens() { + List tokenList = messageRepository.retrieveTokens(MAX_MESSAGES); + return tokenList; + } + + public static String convertToHtml() { + Writer writer = new StringWriter(1024); + new Html(writer) { + { + html(); + head(); + meta().httpEquiv("refresh").content("10").end(); + end(); + body(); + h3().text("Publish a message").end(); + form().action("pubsub/publish").method("POST"); + label().text("Message:").end(); + input().id("payload").type("input").name("payload").end(); + input().id("submit").type("submit").value("Send").end(); + end(); + h3().text("Last received tokens").end(); + table().border("1").cellpadding("10"); + tr(); + th().text("Tokens").end(); + end(); + markupString(getReceivedTokens()); + h3().text("Last received claims").end(); + table().border("1").cellpadding("10"); + tr(); + th().text("Claims").end(); + end(); + markupString(getReceivedClaims()); + h3().text("Last received messages").end(); + table().border("1").cellpadding("10"); + tr(); + th().text("Id").end(); + th().text("Data").end(); + th().text("PublishTime").end(); + end(); + markupMessage(getReceivedMessages()); + endAll(); + done(); + } + + Html markupString(List strings) { + for (String string : strings) { + tr(); + th().text(string).end(); + end(); + } + return end(); + } + + Html markupMessage(List messages) { + for (Message message : messages) { + tr(); + th().text(message.getMessageId()).end(); + th().text(message.getData()).end(); + th().text(message.getPublishTime()).end(); + end(); + } + return end(); + } + }; + return ((StringWriter) writer).getBuffer().toString(); } - private PubSubHome() { } + private PubSubHome() {} } diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPublish.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPublish.java index 73d850284e2..e4915ea131d 100644 --- a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPublish.java +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPublish.java @@ -40,10 +40,11 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) String topicId = System.getenv("PUBSUB_TOPIC"); // create a publisher on the topic if (publisher == null) { - ProjectTopicName topicName = ProjectTopicName.newBuilder() - .setProject(ServiceOptions.getDefaultProjectId()) - .setTopic(topicId) - .build(); + ProjectTopicName topicName = + ProjectTopicName.newBuilder() + .setProject(ServiceOptions.getDefaultProjectId()) + .setTopic(topicId) + .build(); publisher = Publisher.newBuilder(topicName).build(); } // construct a pubsub message from the payload @@ -61,7 +62,7 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) private Publisher publisher; - public PubSubPublish() { } + public PubSubPublish() {} PubSubPublish(Publisher publisher) { this.publisher = publisher; diff --git a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPush.java b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPush.java index 0d3f5a2def6..14f6f9a58bc 100644 --- a/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPush.java +++ b/appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubPush.java @@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +// [START gae_standard_pubsub_push] @WebServlet(value = "/pubsub/push") public class PubSubPush extends HttpServlet { @@ -79,3 +80,4 @@ public PubSubPush() { this.messageRepository = MessageRepositoryImpl.getInstance(); } } +// [END gae_standard_pubsub_push] diff --git a/appengine-java8/pubsub/src/main/webapp/index.jsp b/appengine-java8/pubsub/src/main/webapp/index.jsp index 9b5bc1cfd85..7d358582809 100644 --- a/appengine-java8/pubsub/src/main/webapp/index.jsp +++ b/appengine-java8/pubsub/src/main/webapp/index.jsp @@ -1,24 +1,2 @@ <%@ page import="com.example.appengine.pubsub.PubSubHome" %> - - - - - An example of using PubSub on App Engine Flex - -

Publish a message

-
- - - -
-

Last received messages

- - - - - - - <%= PubSubHome.getReceivedMessages() %> -
IdDataPublishTime
- - +<%= PubSubHome.convertToHtml() %> diff --git a/appengine-java8/remote-client/pom.xml b/appengine-java8/remote-client/pom.xml index 7f2fa9f51c0..6fb57031855 100644 --- a/appengine-java8/remote-client/pom.xml +++ b/appengine-java8/remote-client/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/appengine-java8/remote-server/pom.xml b/appengine-java8/remote-server/pom.xml index 370277788cc..1c7199b9956 100644 --- a/appengine-java8/remote-server/pom.xml +++ b/appengine-java8/remote-server/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/requests/pom.xml b/appengine-java8/requests/pom.xml index 92a8b1d04f1..cdd38ede8e8 100644 --- a/appengine-java8/requests/pom.xml +++ b/appengine-java8/requests/pom.xml @@ -28,7 +28,7 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/search/pom.xml b/appengine-java8/search/pom.xml index 330b175eb4e..06c0fc0a818 100644 --- a/appengine-java8/search/pom.xml +++ b/appengine-java8/search/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/sendgrid/pom.xml b/appengine-java8/sendgrid/pom.xml index 8468695478b..53685e50141 100644 --- a/appengine-java8/sendgrid/pom.xml +++ b/appengine-java8/sendgrid/pom.xml @@ -27,7 +27,7 @@ Copyright 2018 Google LLC com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/appengine-java8/spanner/pom.xml b/appengine-java8/spanner/pom.xml index a56473a5bdd..74c16307af4 100644 --- a/appengine-java8/spanner/pom.xml +++ b/appengine-java8/spanner/pom.xml @@ -30,7 +30,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/static-files/pom.xml b/appengine-java8/static-files/pom.xml index d273beacd1a..61bf7ce92b5 100644 --- a/appengine-java8/static-files/pom.xml +++ b/appengine-java8/static-files/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/taskqueues-deferred/pom.xml b/appengine-java8/taskqueues-deferred/pom.xml index 8487641d536..f7bf51de193 100644 --- a/appengine-java8/taskqueues-deferred/pom.xml +++ b/appengine-java8/taskqueues-deferred/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/taskqueues-pull/pom.xml b/appengine-java8/taskqueues-pull/pom.xml index 84abc1b73ad..bb8dba4e911 100644 --- a/appengine-java8/taskqueues-pull/pom.xml +++ b/appengine-java8/taskqueues-pull/pom.xml @@ -30,7 +30,7 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/taskqueues-push/pom.xml b/appengine-java8/taskqueues-push/pom.xml index 30aed77fbcb..fc3d31d0099 100644 --- a/appengine-java8/taskqueues-push/pom.xml +++ b/appengine-java8/taskqueues-push/pom.xml @@ -28,7 +28,7 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/tasks/README.md b/appengine-java8/tasks/README.md index 00aee8be961..8fc7231896c 100644 --- a/appengine-java8/tasks/README.md +++ b/appengine-java8/tasks/README.md @@ -69,12 +69,15 @@ location is "us-central1"). export LOCATION_ID= ``` +### Using App Engine Queues Create a task, targeted at the `/tasks/create` endpoint, with a payload specified: ``` mvn exec:java -Dexec.mainClass="com.example.task.CreateTask" \ -Dexec.args="--project-id $GOOGLE_CLOUD_PROJECT \ - --queue $QUEUE_ID --location $LOCATION_ID --payload hello" + --queue $QUEUE_ID \ + --location $LOCATION_ID \ + --payload hello" ``` The App Engine app serves as a target for the push requests. It has an diff --git a/appengine-java8/tasks/pom.xml b/appengine-java8/tasks/pom.xml index 2f5ba869b8a..06e9633d782 100644 --- a/appengine-java8/tasks/pom.xml +++ b/appengine-java8/tasks/pom.xml @@ -30,7 +30,7 @@ Copyright 2018 Google LLC com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 @@ -52,7 +52,7 @@ Copyright 2018 Google LLC com.google.cloud google-cloud-tasks - 0.86.0-beta + 0.88.0-beta commons-cli diff --git a/appengine-java8/tasks/src/main/java/com/example/task/CreateTask.java b/appengine-java8/tasks/src/main/java/com/example/task/CreateTask.java index a2d83575523..2609cbcd8fc 100644 --- a/appengine-java8/tasks/src/main/java/com/example/task/CreateTask.java +++ b/appengine-java8/tasks/src/main/java/com/example/task/CreateTask.java @@ -161,8 +161,8 @@ private static void printUsage(Options options) { HelpFormatter formatter = new HelpFormatter(); formatter.printHelp( "client", - "A simple Cloud Tasks command line client that triggers a call to an AppEngine " - + "endpoint.", + "A simple Cloud Tasks command line client that creates a task with an " + + "App Engine endpoint.", options, "", true); throw new RuntimeException(); } diff --git a/appengine-java8/tasks/src/main/java/com/example/task/TaskServlet.java b/appengine-java8/tasks/src/main/java/com/example/task/TaskServlet.java index 141f9264047..adbef6c37c7 100644 --- a/appengine-java8/tasks/src/main/java/com/example/task/TaskServlet.java +++ b/appengine-java8/tasks/src/main/java/com/example/task/TaskServlet.java @@ -38,7 +38,7 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOEx String body = req.getReader() .lines() .reduce("", (accumulator, actual) -> accumulator + actual); - + if (!body.isEmpty()) { log.info("Request payload: " + body); String output = String.format("Received task with payload %s", body); diff --git a/appengine-java8/translate-pubsub/pom.xml b/appengine-java8/translate-pubsub/pom.xml index e7e6c4f9522..52390da068d 100644 --- a/appengine-java8/translate-pubsub/pom.xml +++ b/appengine-java8/translate-pubsub/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/twilio/pom.xml b/appengine-java8/twilio/pom.xml index 97935a51fa2..2a9392ff8e5 100644 --- a/appengine-java8/twilio/pom.xml +++ b/appengine-java8/twilio/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/urlfetch/pom.xml b/appengine-java8/urlfetch/pom.xml index f58eca6bd00..d5f8825e145 100644 --- a/appengine-java8/urlfetch/pom.xml +++ b/appengine-java8/urlfetch/pom.xml @@ -27,7 +27,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine-java8/urlfetch/src/main/java/com/example/appengine/UrlFetchServlet.java b/appengine-java8/urlfetch/src/main/java/com/example/appengine/UrlFetchServlet.java index 426e3fa56f2..1d692644499 100644 --- a/appengine-java8/urlfetch/src/main/java/com/example/appengine/UrlFetchServlet.java +++ b/appengine-java8/urlfetch/src/main/java/com/example/appengine/UrlFetchServlet.java @@ -97,7 +97,7 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) int respCode = conn.getResponseCode(); // New items get NOT_FOUND on PUT if (respCode == HttpURLConnection.HTTP_OK || respCode == HttpURLConnection.HTTP_NOT_FOUND) { req.setAttribute("error", ""); - StringBuffer response = new StringBuffer(); + StringBuilder response = new StringBuilder(); String line; // Read input data stream. diff --git a/appengine-java8/users/pom.xml b/appengine-java8/users/pom.xml index 579c05bdeb7..586840c7534 100644 --- a/appengine-java8/users/pom.xml +++ b/appengine-java8/users/pom.xml @@ -29,7 +29,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/appengine-java8/websocket-jsr356/pom.xml b/appengine-java8/websocket-jsr356/pom.xml index 7149dd9b227..691198d717e 100644 --- a/appengine-java8/websocket-jsr356/pom.xml +++ b/appengine-java8/websocket-jsr356/pom.xml @@ -27,7 +27,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/appengine/analytics/pom.xml b/appengine/analytics/pom.xml index cfbf215fd31..84f52d505e3 100644 --- a/appengine/analytics/pom.xml +++ b/appengine/analytics/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/appidentity/pom.xml b/appengine/appidentity/pom.xml index 8468eb30f42..33a11ce1461 100644 --- a/appengine/appidentity/pom.xml +++ b/appengine/appidentity/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/cloudsql/pom.xml b/appengine/cloudsql/pom.xml index deed89393af..9a73340648b 100644 --- a/appengine/cloudsql/pom.xml +++ b/appengine/cloudsql/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -44,8 +44,8 @@ 1.0.0 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/datastore/indexes-exploding/pom.xml b/appengine/datastore/indexes-exploding/pom.xml index 4b1fdbb5bfd..acfb50f1878 100644 --- a/appengine/datastore/indexes-exploding/pom.xml +++ b/appengine/datastore/indexes-exploding/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/datastore/indexes-perfect/pom.xml b/appengine/datastore/indexes-perfect/pom.xml index a6bbeb951ff..4faa0628cd2 100644 --- a/appengine/datastore/indexes-perfect/pom.xml +++ b/appengine/datastore/indexes-perfect/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/datastore/indexes/pom.xml b/appengine/datastore/indexes/pom.xml index c11a048e5b0..842b8b409da 100644 --- a/appengine/datastore/indexes/pom.xml +++ b/appengine/datastore/indexes/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/datastore/pom.xml b/appengine/datastore/pom.xml deleted file mode 100644 index db752039308..00000000000 --- a/appengine/datastore/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - 4.0.0 - pom - 1.0-SNAPSHOT - com.example.appengine - appengine-datastore - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - 1.7 - 1.7 - - - - indexes - indexes-exploding - indexes-perfect - - diff --git a/appengine/endpoints-frameworks-v2/backend/pom.xml b/appengine/endpoints-frameworks-v2/backend/pom.xml index 9ce559f55b7..692a08b0e70 100644 --- a/appengine/endpoints-frameworks-v2/backend/pom.xml +++ b/appengine/endpoints-frameworks-v2/backend/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -41,8 +41,8 @@ 2.2.1 YOUR_PROJECT_ID - 1.7 - 1.7 + 1.8 + 1.8 1.3.2 diff --git a/appengine/endpoints-frameworks-v2/guice-example/pom.xml b/appengine/endpoints-frameworks-v2/guice-example/pom.xml index 2c5d4799800..b997690d22e 100644 --- a/appengine/endpoints-frameworks-v2/guice-example/pom.xml +++ b/appengine/endpoints-frameworks-v2/guice-example/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -42,8 +42,8 @@ 2.2.1 YOUR_PROJECT_ID - 1.7 - 1.7 + 1.8 + 1.8 1.3.2 diff --git a/appengine/endpoints-frameworks-v2/migration-example/pom.xml b/appengine/endpoints-frameworks-v2/migration-example/pom.xml index 96d15fe6512..6eaf5aeca25 100644 --- a/appengine/endpoints-frameworks-v2/migration-example/pom.xml +++ b/appengine/endpoints-frameworks-v2/migration-example/pom.xml @@ -29,7 +29,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -38,8 +38,8 @@ limitations under the License. - 1.7 - 1.7 + 1.8 + 1.8 UTF-8 diff --git a/appengine/endpoints-v1-helloworld/pom.xml b/appengine/endpoints-v1-helloworld/pom.xml index 2f6c015b5a1..4136acbdbc5 100644 --- a/appengine/endpoints-v1-helloworld/pom.xml +++ b/appengine/endpoints-v1-helloworld/pom.xml @@ -28,14 +28,14 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 UTF-8 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/firebase-event-proxy/gae-firebase-event-proxy/pom.xml b/appengine/firebase-event-proxy/gae-firebase-event-proxy/pom.xml index e9ddb4b9a2a..9eed251b6f0 100644 --- a/appengine/firebase-event-proxy/gae-firebase-event-proxy/pom.xml +++ b/appengine/firebase-event-proxy/gae-firebase-event-proxy/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -36,8 +36,8 @@ 1 UTF-8 true - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/firebase-tictactoe/pom.xml b/appengine/firebase-tictactoe/pom.xml index 414acab4ed1..0703152d668 100644 --- a/appengine/firebase-tictactoe/pom.xml +++ b/appengine/firebase-tictactoe/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/gaeinfo/pom.xml b/appengine/gaeinfo/pom.xml index 7a8a8e3e94e..bd8cdf7996c 100644 --- a/appengine/gaeinfo/pom.xml +++ b/appengine/gaeinfo/pom.xml @@ -28,14 +28,14 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/guestbook-cloud-datastore/pom.xml b/appengine/guestbook-cloud-datastore/pom.xml index 21dfd457a62..8415e45dddf 100644 --- a/appengine/guestbook-cloud-datastore/pom.xml +++ b/appengine/guestbook-cloud-datastore/pom.xml @@ -29,15 +29,15 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 com.example.appengine appengine-guestbook-cloud-datastore 19.0 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/guestbook-objectify/pom.xml b/appengine/guestbook-objectify/pom.xml index 597984a5522..e237423209a 100644 --- a/appengine/guestbook-objectify/pom.xml +++ b/appengine/guestbook-objectify/pom.xml @@ -25,8 +25,8 @@ 5.1.21 20.0 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/helloworld-new-plugins/pom.xml b/appengine/helloworld-new-plugins/pom.xml index 2b7b766ca3a..5d2e6e8a873 100644 --- a/appengine/helloworld-new-plugins/pom.xml +++ b/appengine/helloworld-new-plugins/pom.xml @@ -23,8 +23,8 @@ Copyright 2015 Google Inc. - 1.7 - 1.7 + 1.8 + 1.8 @@ -35,7 +35,7 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/appengine/helloworld/pom.xml b/appengine/helloworld/pom.xml index 14d2258be05..dc55cd3e2e5 100644 --- a/appengine/helloworld/pom.xml +++ b/appengine/helloworld/pom.xml @@ -28,9 +28,15 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + + UTF-8 + 1.8 + 1.8 + + javax.servlet diff --git a/appengine/iap/pom.xml b/appengine/iap/pom.xml index fad52b75a1e..4af32ea3e13 100644 --- a/appengine/iap/pom.xml +++ b/appengine/iap/pom.xml @@ -27,9 +27,15 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + + UTF-8 + 1.8 + 1.8 + + javax.servlet diff --git a/appengine/images/pom.xml b/appengine/images/pom.xml index 8da3410cbd3..691bd805ef0 100644 --- a/appengine/images/pom.xml +++ b/appengine/images/pom.xml @@ -20,10 +20,6 @@ Copyright 2015 Google Inc. com.example.appengine appengine-images - - 1.9.73 - - diff --git a/appengine/oauth2/pom.xml b/appengine/oauth2/pom.xml index 06f4fa1da2f..52032b99a80 100644 --- a/appengine/oauth2/pom.xml +++ b/appengine/oauth2/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/pom.xml b/appengine/pom.xml deleted file mode 100644 index 8f4657d8e00..00000000000 --- a/appengine/pom.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - 4.0.0 - 1.0.0 - com.google.cloud - appengine-doc-samples - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - - - analytics - appidentity - cloudsql - datastore - - endpoints-frameworks-v2/backend - endpoints-frameworks-v2/migration-example - endpoints-frameworks-v2/guice-example - - endpoints-v1-helloworld - - firebase-event-proxy/gae-firebase-event-proxy - firebase-tictactoe - gaeinfo - - guestbook-objectify - helloworld - helloworld-new-plugins - iap - images - logs - mail - mailgun - mailjet - memcache - multitenancy - oauth2 - pusher-chat - requests - search - sendgrid - - remote/remote-client - remote/remote-server - - sockets - static-files - taskqueue - twilio - urlfetch - users - - - diff --git a/appengine/pusher-chat/pom.xml b/appengine/pusher-chat/pom.xml index bdb33578c06..25e605a625b 100644 --- a/appengine/pusher-chat/pom.xml +++ b/appengine/pusher-chat/pom.xml @@ -27,13 +27,13 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/remote/remote-client/pom.xml b/appengine/remote/remote-client/pom.xml index 2cc9b4c2b05..464018f02fc 100644 --- a/appengine/remote/remote-client/pom.xml +++ b/appengine/remote/remote-client/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/remote/remote-server/pom.xml b/appengine/remote/remote-server/pom.xml index 2a7a64b6c0d..f09ad3da0c7 100644 --- a/appengine/remote/remote-server/pom.xml +++ b/appengine/remote/remote-server/pom.xml @@ -27,12 +27,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/requests/pom.xml b/appengine/requests/pom.xml index 90924be244e..7dba8468795 100644 --- a/appengine/requests/pom.xml +++ b/appengine/requests/pom.xml @@ -28,12 +28,12 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/search/pom.xml b/appengine/search/pom.xml index 9487fbd5f9a..71873c2ba49 100644 --- a/appengine/search/pom.xml +++ b/appengine/search/pom.xml @@ -27,9 +27,15 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + + UTF-8 + 1.8 + 1.8 + + com.google.appengine diff --git a/appengine/sendgrid/pom.xml b/appengine/sendgrid/pom.xml index c13e7cb6c67..b0fe3d932e1 100644 --- a/appengine/sendgrid/pom.xml +++ b/appengine/sendgrid/pom.xml @@ -27,9 +27,15 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + + UTF-8 + 1.8 + 1.8 + + javax.servlet diff --git a/appengine/sockets/pom.xml b/appengine/sockets/pom.xml index 4df96d363a6..44acb074364 100755 --- a/appengine/sockets/pom.xml +++ b/appengine/sockets/pom.xml @@ -33,13 +33,13 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/static-files/pom.xml b/appengine/static-files/pom.xml index 45d95ffb8b7..5e9dd2a3cd3 100644 --- a/appengine/static-files/pom.xml +++ b/appengine/static-files/pom.xml @@ -27,12 +27,12 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/taskqueue/defer-samples/pom.xml b/appengine/taskqueue/defer-samples/pom.xml index 9a274081636..80930b53fb2 100644 --- a/appengine/taskqueue/defer-samples/pom.xml +++ b/appengine/taskqueue/defer-samples/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -35,8 +35,8 @@ - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/taskqueue/pom.xml b/appengine/taskqueue/pom.xml deleted file mode 100644 index d574b7f9f5f..00000000000 --- a/appengine/taskqueue/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - 1.0.0 - - com.google.cloud - taskqueue-doc-samples - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - push-samples - pull-samples - defer-samples - - - diff --git a/appengine/taskqueue/pull-samples/pom.xml b/appengine/taskqueue/pull-samples/pom.xml index 102e4da17b8..2c2f7b59751 100644 --- a/appengine/taskqueue/pull-samples/pom.xml +++ b/appengine/taskqueue/pull-samples/pom.xml @@ -29,12 +29,12 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/taskqueue/push-samples/pom.xml b/appengine/taskqueue/push-samples/pom.xml index 70c12dea2a8..91bac7b8a4b 100644 --- a/appengine/taskqueue/push-samples/pom.xml +++ b/appengine/taskqueue/push-samples/pom.xml @@ -28,12 +28,12 @@ Copyright 2016 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/twilio/pom.xml b/appengine/twilio/pom.xml index b149611525c..6ffe86273bd 100644 --- a/appengine/twilio/pom.xml +++ b/appengine/twilio/pom.xml @@ -27,12 +27,12 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/urlfetch/pom.xml b/appengine/urlfetch/pom.xml index 1eafa142642..2be46850770 100644 --- a/appengine/urlfetch/pom.xml +++ b/appengine/urlfetch/pom.xml @@ -27,12 +27,12 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/appengine/users/pom.xml b/appengine/users/pom.xml index 9323806ce97..a9d5181317b 100644 --- a/appengine/users/pom.xml +++ b/appengine/users/pom.xml @@ -30,9 +30,15 @@ Copyright 2015 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + + UTF-8 + 1.8 + 1.8 + + com.google.appengine diff --git a/asset/cloud-client/pom.xml b/asset/cloud-client/pom.xml index 47f56c9601f..48f4ac69e77 100644 --- a/asset/cloud-client/pom.xml +++ b/asset/cloud-client/pom.xml @@ -23,7 +23,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/auth/pom.xml b/auth/pom.xml index 3debb027b95..1679b167ae8 100644 --- a/auth/pom.xml +++ b/auth/pom.xml @@ -28,7 +28,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/bigquery/bigquerystorage/pom.xml b/bigquery/bigquerystorage/pom.xml index 4bd34863812..147700d497b 100644 --- a/bigquery/bigquerystorage/pom.xml +++ b/bigquery/bigquerystorage/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/bigquery/cloud-client/pom.xml b/bigquery/cloud-client/pom.xml index 19d3600bee5..d173f9033e4 100644 --- a/bigquery/cloud-client/pom.xml +++ b/bigquery/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/bigquery/datatransfer/cloud-client/pom.xml b/bigquery/datatransfer/cloud-client/pom.xml index 6b5181b2dbc..a68931e5de8 100644 --- a/bigquery/datatransfer/cloud-client/pom.xml +++ b/bigquery/datatransfer/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/bigquery/rest/pom.xml b/bigquery/rest/pom.xml index b24331408da..b675dfba7ab 100644 --- a/bigquery/rest/pom.xml +++ b/bigquery/rest/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/bigtable/pom.xml b/bigtable/pom.xml new file mode 100644 index 00000000000..86934be3887 --- /dev/null +++ b/bigtable/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + com.m.examples.bigtable + bigtable + 1.0-SNAPSHOT + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + bigtable + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + + com.google.cloud + google-cloud-bigtable + 0.92.0-alpha + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/bigtable/src/main/java/com/m/examples/bigtable/HelloWorld.java b/bigtable/src/main/java/com/m/examples/bigtable/HelloWorld.java new file mode 100644 index 00000000000..36e1fc08f9a --- /dev/null +++ b/bigtable/src/main/java/com/m/examples/bigtable/HelloWorld.java @@ -0,0 +1,187 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +// [START bigtable_hw_imports_veneer] +import com.google.api.gax.rpc.NotFoundException; +import com.google.api.gax.rpc.ServerStream; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.models.Query; +import com.google.cloud.bigtable.data.v2.models.Row; +import com.google.cloud.bigtable.data.v2.models.RowCell; +import com.google.cloud.bigtable.data.v2.models.RowMutation; +import java.io.IOException; + +// [END bigtable_hw_imports_veneer] + +/** + * An example of using Google Cloud Bigtable. + * + *

This example is a very simple "hello world" application, that illustrates how to create a new + * table, write to the table, read the data back, and delete the table. + * + *

    + *
  • create table + *
  • read single row + *
  • read table + *
  • delete table + *
+ */ +public class HelloWorld { + + private static final String COLUMN_FAMILY = "cf1"; + private static final String COLUMN_QUALIFIER = "greeting"; + private static final String ROW_KEY_PREFIX = "rowKey"; + private final String tableId; + private final BigtableDataClient dataClient; + private final BigtableTableAdminClient adminClient; + + public static void main(String[] args) throws Exception { + + if (args.length != 2) { + System.out.println("Missing required project id or instance id"); + return; + } + String projectId = args[0]; + String instanceId = args[1]; + + HelloWorld helloWorld = new HelloWorld(projectId, instanceId, "test-table"); + helloWorld.run(); + } + + public HelloWorld(String projectId, String instanceId, String tableId) throws IOException { + this.tableId = tableId; + + // [START bigtable_hw_connect_veneer] + // Creates the settings to configure a bigtable data client. + BigtableDataSettings settings = + BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId).build(); + + // Creates a bigtable data client. + dataClient = BigtableDataClient.create(settings); + + // Creates the settings to configure a bigtable table admin client. + BigtableTableAdminSettings adminSettings = + BigtableTableAdminSettings.newBuilder() + .setProjectId(projectId) + .setInstanceId(instanceId) + .build(); + + // Creates a bigtable table admin client. + adminClient = BigtableTableAdminClient.create(adminSettings); + // [END bigtable_hw_connect_veneer] + } + + public void run() throws Exception { + createTable(); + writeToTable(); + readSingleRow(); + readTable(); + deleteTable(); + dataClient.close(); + adminClient.close(); + } + + /** Demonstrates how to create a table. */ + public void createTable() { + // [START bigtable_hw_create_table_veneer] + // Checks if table exists, creates table if does not exist. + if (!adminClient.exists(tableId)) { + System.out.println("Creating table: " + tableId); + CreateTableRequest createTableRequest = + CreateTableRequest.of(tableId).addFamily(COLUMN_FAMILY); + adminClient.createTable(createTableRequest); + System.out.printf("Table %s created successfully%n", tableId); + } + // [END bigtable_hw_create_table_veneer] + } + + /** Demonstrates how to write some rows to a table. */ + public void writeToTable() { + // [START bigtable_hw_write_rows_veneer] + try { + System.out.println("\nWriting some greetings to the table"); + String[] greetings = {"Hello World!", "Hello Bigtable!", "Hello Java!"}; + for (int i = 0; i < greetings.length; i++) { + RowMutation rowMutation = + RowMutation.create(tableId, ROW_KEY_PREFIX + i) + .setCell(COLUMN_FAMILY, COLUMN_QUALIFIER, greetings[i]); + dataClient.mutateRow(rowMutation); + System.out.println(greetings[i]); + } + } catch (NotFoundException e) { + System.err.println("Failed to write to non-existent table: " + e.getMessage()); + } + // [END bigtable_hw_write_rows_veneer] + } + + /** Demonstrates how to read a single row from a table. */ + public void readSingleRow() { + // [START bigtable_hw_get_by_key_veneer] + try { + System.out.println("\nReading a single row by row key"); + Row row = dataClient.readRow(tableId, ROW_KEY_PREFIX + 0); + System.out.println("Row: " + row.getKey().toStringUtf8()); + for (RowCell cell : row.getCells()) { + System.out.printf( + "Family: %s Qualifier: %s Value: %s%n", + cell.getFamily(), cell.getQualifier().toStringUtf8(), cell.getValue().toStringUtf8()); + } + } catch (NotFoundException e) { + System.err.println("Failed to read from a non-existent table: " + e.getMessage()); + } + // [END bigtable_hw_get_by_key_veneer] + } + + /** Demonstrates how to read an entire table. */ + public void readTable() { + // [START bigtable_hw_scan_all_veneer] + try { + System.out.println("\nReading the entire table"); + Query query = Query.create(tableId); + ServerStream rowStream = dataClient.readRows(query); + for (Row r : rowStream) { + System.out.println("Row Key: " + r.getKey().toStringUtf8()); + for (RowCell cell : r.getCells()) { + System.out.printf( + "Family: %s Qualifier: %s Value: %s%n", + cell.getFamily(), cell.getQualifier().toStringUtf8(), cell.getValue().toStringUtf8()); + } + } + } catch (NotFoundException e) { + System.err.println("Failed to read a non-existent table: " + e.getMessage()); + } + // [END bigtable_hw_scan_all_veneer] + } + + /** Demonstrates how to delete a table. */ + public void deleteTable() { + // [START bigtable_hw_delete_table_veneer] + System.out.println("\nDeleting table: " + tableId); + try { + adminClient.deleteTable(tableId); + System.out.printf("Table %s deleted successfully%n", tableId); + } catch (NotFoundException e) { + System.err.println("Failed to delete a non-existent table: " + e.getMessage()); + } + // [END bigtable_hw_delete_table_veneer] + } +} diff --git a/bigtable/src/main/java/com/m/examples/bigtable/InstanceAdminExample.java b/bigtable/src/main/java/com/m/examples/bigtable/InstanceAdminExample.java new file mode 100644 index 00000000000..3b317d594cd --- /dev/null +++ b/bigtable/src/main/java/com/m/examples/bigtable/InstanceAdminExample.java @@ -0,0 +1,215 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +import com.google.api.gax.rpc.AlreadyExistsException; +import com.google.api.gax.rpc.NotFoundException; +import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.Cluster; +import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest; +import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; +import com.google.cloud.bigtable.admin.v2.models.Instance; +import com.google.cloud.bigtable.admin.v2.models.PartialListInstancesException; +import com.google.cloud.bigtable.admin.v2.models.StorageType; +import java.io.IOException; +import java.util.List; +import java.util.Map; + +/** + * An example of using Google Cloud Bigtable. + * + *

This example demonstrates the usage of BigtableInstanceAdminClient to create, configure, and + * delete Cloud Bigtable Instances and Clusters. + * + *

    + *
  • creates production instance + *
  • lists instances + *
  • gets instance + *
  • lists clusters + *
  • adds cluster + *
  • deletes cluster + *
  • deletes instance + *
+ */ +public class InstanceAdminExample { + + private static final String CLUSTER = "cluster"; + private final String clusterId; + private final String instanceId; + private final BigtableInstanceAdminClient adminClient; + + public static void main(String[] args) throws IOException { + + if (args.length != 1) { + System.out.println("Missing required project id"); + return; + } + String projectId = args[0]; + + InstanceAdminExample instanceAdmin = + new InstanceAdminExample(projectId, "ssd-instance", "ssd-cluster"); + instanceAdmin.run(); + } + + public InstanceAdminExample(String projectId, String instanceId, String clusterId) + throws IOException { + this.instanceId = instanceId; + this.clusterId = clusterId; + + // Creates the settings to configure a bigtable instance admin client. + BigtableInstanceAdminSettings instanceAdminSettings = + BigtableInstanceAdminSettings.newBuilder().setProjectId(projectId).build(); + + // Creates a bigtable instance admin client. + adminClient = BigtableInstanceAdminClient.create(instanceAdminSettings); + } + + public void run() { + createProdInstance(); + listInstances(); + getInstance(); + listClusters(); + addCluster(); + deleteCluster(); + deleteInstance(); + adminClient.close(); + } + + /** Demonstrates how to create a Production instance within a provided project. */ + public void createProdInstance() { + // Checks if instance exists, creates instance if does not exists. + if (!adminClient.exists(instanceId)) { + System.out.println("Instance does not exist, creating a PRODUCTION instance"); + // [START bigtable_create_prod_instance] + // Creates a Production Instance with the ID "ssd-instance", + // cluster id "ssd-cluster", 3 nodes and location "us-central1-f". + CreateInstanceRequest createInstanceRequest = + CreateInstanceRequest.of(instanceId) + .addCluster(clusterId, "us-central1-f", 3, StorageType.SSD) + .setType(Instance.Type.PRODUCTION) + .addLabel("department", "accounting"); + // Creates a production instance with the given request. + try { + Instance instance = adminClient.createInstance(createInstanceRequest); + System.out.printf("PRODUCTION type instance %s created successfully%n", instance.getId()); + } catch (Exception e) { + System.err.println("Failed to create instance: " + e.getMessage()); + throw e; + } + // [END bigtable_create_prod_instance] + } + } + + /** Demonstrates how to list all instances within a project. */ + public void listInstances() { + System.out.println("\nListing Instances"); + // [START bigtable_list_instances] + try { + List instances = adminClient.listInstances(); + for (Instance instance : instances) { + System.out.println(instance.getId()); + } + } catch (PartialListInstancesException e) { + System.err.println("Failed to list instances: " + e.getMessage()); + System.err.println("The following zones are unavailable: " + e.getUnavailableZones()); + System.err.println("But the following instances are reachable: " + e.getInstances()); + } + // [END bigtable_list_instances] + } + + /** Demonstrates how to get an instance. */ + public Instance getInstance() { + System.out.println("\nGet Instance"); + // [START bigtable_get_instance] + Instance instance = null; + try { + instance = adminClient.getInstance(instanceId); + System.out.println("Instance ID: " + instance.getId()); + System.out.println("Display Name: " + instance.getDisplayName()); + System.out.print("Labels: "); + Map labels = instance.getLabels(); + for (String key : labels.keySet()) { + System.out.printf("%s - %s", key, labels.get(key)); + } + System.out.println("\nState: " + instance.getState()); + System.out.println("Type: " + instance.getType()); + } catch (NotFoundException e) { + System.err.println("Failed to get non-existent instance: " + e.getMessage()); + } + // [END bigtable_get_instance] + return instance; + } + + /** Demonstrates how to list clusters within an instance. */ + public void listClusters() { + System.out.println("\nListing Clusters"); + // [START bigtable_get_clusters] + try { + List clusters = adminClient.listClusters(instanceId); + for (Cluster cluster : clusters) { + System.out.println(cluster.getId()); + } + } catch (NotFoundException e) { + System.err.println("Failed to list clusters from a non-existent instance: " + e.getMessage()); + } + // [END bigtable_get_clusters] + } + + /** Demonstrates how to delete an instance. */ + public void deleteInstance() { + System.out.println("\nDeleting Instance"); + // [START bigtable_delete_instance] + try { + adminClient.deleteInstance(instanceId); + System.out.println("Instance deleted: " + instanceId); + } catch (NotFoundException e) { + System.err.println("Failed to delete non-existent instance: " + e.getMessage()); + } + // [END bigtable_delete_instance] + } + + /** Demonstrates how to add a cluster to an instance. */ + public void addCluster() { + System.out.printf("%nAdding cluster: %s to instance: %s%n", CLUSTER, instanceId); + // [START bigtable_create_cluster] + try { + adminClient.createCluster( + CreateClusterRequest.of(instanceId, CLUSTER) + .setZone("us-central1-c") + .setServeNodes(3) + .setStorageType(StorageType.SSD)); + System.out.printf("Cluster: %s created successfully%n", CLUSTER); + } catch (AlreadyExistsException e) { + System.err.println("Failed to add cluster, already exists: " + e.getMessage()); + } + // [END bigtable_create_cluster] + } + + /** Demonstrates how to delete a cluster from an instance. */ + public void deleteCluster() { + System.out.printf("%nDeleting cluster: %s from instance: %s%n", CLUSTER, instanceId); + // [START bigtable_delete_cluster] + try { + adminClient.deleteCluster(instanceId, CLUSTER); + System.out.printf("Cluster: %s deleted successfully%n", CLUSTER); + } catch (NotFoundException e) { + System.err.println("Failed to delete a non-existent cluster: " + e.getMessage()); + } + // [END bigtable_delete_cluster] + } +} diff --git a/bigtable/src/main/java/com/m/examples/bigtable/Quickstart.java b/bigtable/src/main/java/com/m/examples/bigtable/Quickstart.java new file mode 100644 index 00000000000..4d520614281 --- /dev/null +++ b/bigtable/src/main/java/com/m/examples/bigtable/Quickstart.java @@ -0,0 +1,59 @@ +/* + * Copyright 2019 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.m.examples.bigtable; + +// START [bigtable_quickstart_veneer] + +import com.google.api.gax.rpc.NotFoundException; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.models.Row; +import com.google.cloud.bigtable.data.v2.models.RowCell; + +public class Quickstart { + + public static void quickstart(String projectId, String instanceId, String tableId) { + // String projectId = "my-project-id"; + // String instanceId = "my-instance-id"; + // String tableId = "my-table-id"; + + BigtableDataSettings settings = + BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId).build(); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. + try (BigtableDataClient dataClient = BigtableDataClient.create(settings)) { + try { + System.out.println("\nReading a single row by row key"); + Row row = dataClient.readRow(tableId, "r1"); + System.out.println("Row: " + row.getKey().toStringUtf8()); + for (RowCell cell : row.getCells()) { + System.out.printf( + "Family: %s Qualifier: %s Value: %s%n", + cell.getFamily(), cell.getQualifier().toStringUtf8(), cell.getValue().toStringUtf8()); + } + } catch (NotFoundException e) { + System.err.println("Failed to read from a non-existent table: " + e.getMessage()); + } + + } catch (Exception e) { + System.out.println("Error during functionName: \n" + e.toString()); + } + } +} +// END [bigtable_quickstart_veneer] diff --git a/bigtable/src/main/java/com/m/examples/bigtable/TableAdminExample.java b/bigtable/src/main/java/com/m/examples/bigtable/TableAdminExample.java new file mode 100644 index 00000000000..56c47e19a32 --- /dev/null +++ b/bigtable/src/main/java/com/m/examples/bigtable/TableAdminExample.java @@ -0,0 +1,385 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; + +import com.google.api.gax.rpc.AlreadyExistsException; +import com.google.api.gax.rpc.NotFoundException; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.ColumnFamily; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.GCRules.DurationRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.IntersectionRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.UnionRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.VersionRule; +import com.google.cloud.bigtable.admin.v2.models.ModifyColumnFamiliesRequest; +import com.google.cloud.bigtable.admin.v2.models.Table; +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * An example of using Google Cloud Bigtable. + * + *

This example demonstrates the usage of BigtableTableAdminClient to create, configure and + * delete a Cloud Bigtable table. + * + *

    + *
  • creates table + *
  • lists all tables + *
  • gets table metadata + *
  • creates DurationRule + *
  • creates VersionRule + *
  • creates UnionRule + *
  • creates IntersectionRule + *
  • creates nested rule + *
  • lists column families + *
  • modifies column family rule + *
  • prints modified column family + *
  • deletes column family + *
  • deletes table + *
+ */ +public class TableAdminExample { + + private static final String COLUMN_FAMILY_1 = "cf1"; + private static final String COLUMN_FAMILY_2 = "cf2"; + private static final String COLUMN_FAMILY_3 = "cf3"; + private static final String COLUMN_FAMILY_4 = "cf4"; + private static final String COLUMN_FAMILY_5 = "cf5"; + private final String tableId; + private final BigtableTableAdminClient adminClient; + + public static void main(String[] args) throws IOException { + + if (args.length != 2) { + System.out.println("Missing required project id or instance id"); + return; + } + String projectId = args[0]; + String instanceId = args[1]; + + TableAdminExample tableAdmin = new TableAdminExample(projectId, instanceId, "test-table"); + tableAdmin.run(); + } + + public TableAdminExample(String projectId, String instanceId, String tableId) throws IOException { + this.tableId = tableId; + + // Creates the settings to configure a bigtable table admin client. + BigtableTableAdminSettings adminSettings = + BigtableTableAdminSettings.newBuilder() + .setProjectId(projectId) + .setInstanceId(instanceId) + .build(); + + // Creates a bigtable table admin client. + adminClient = BigtableTableAdminClient.create(adminSettings); + } + + public void run() { + createTable(); + listAllTables(); + getTableMeta(); + addFamilyWithMaxAgeRule(); + addFamilyWithMaxVersionsRule(); + addFamilyWithUnionRule(); + addFamilyWithIntersectionRule(); + addFamilyWithNestedRule(); + listColumnFamilies(); + modifyColumnFamilyRule(); + printModifiedColumnFamily(); + deleteColumnFamily(); + deleteTable(); + adminClient.close(); + } + + /** Demonstrates how to create a table with the specified configuration. */ + public void createTable() { + // [START bigtable_create_table] + // Checks if table exists, creates table if does not exist. + if (!adminClient.exists(tableId)) { + System.out.println("Table does not exist, creating table: " + tableId); + CreateTableRequest createTableRequest = CreateTableRequest.of(tableId).addFamily("cf"); + Table table = adminClient.createTable(createTableRequest); + System.out.printf("Table: %s created successfully%n", table.getId()); + } + // [END bigtable_create_table] + } + + /** Demonstrates how to list all tables within an instance. */ + public void listAllTables() { + System.out.println("\nListing tables in current instance"); + // [START bigtable_list_tables] + // Lists tables in the current instance. + try { + List tableIds = adminClient.listTables(); + for (String tableId : tableIds) { + System.out.println(tableId); + } + } catch (NotFoundException e) { + System.err.println("Failed to list tables from a non-existent instance: " + e.getMessage()); + } + // [END bigtable_list_tables] + } + + /** Demonstrates how to get a table's metadata. */ + public void getTableMeta() { + System.out.println("\nPrinting table metadata"); + // [START bigtable_get_table_metadata] + // Gets table metadata, and applies a view to the table fields. + try { + Table table = adminClient.getTable(tableId); + System.out.println("Table: " + table.getId()); + Collection columnFamilies = table.getColumnFamilies(); + for (ColumnFamily columnFamily : columnFamilies) { + System.out.printf( + "Column family: %s%nGC Rule: %s%n", + columnFamily.getId(), columnFamily.getGCRule().toString()); + } + } catch (NotFoundException e) { + System.err.println( + "Failed to retrieve table metadata for a non-existent table: " + e.getMessage()); + } + // [END bigtable_get_table_metadata] + } + + /** Demonstrates how to create a new instance of the DurationRule. */ + public void addFamilyWithMaxAgeRule() { + System.out.printf("%nCreating column family %s with max age GC rule%n", COLUMN_FAMILY_1); + // [START bigtable_create_family_gc_max_age] + // Creates a column family with GC policy : maximum age + // where age = current time minus cell timestamp + + // Defines the GC rule to retain data with max age of 5 days. + DurationRule maxAgeRule = GCRULES.maxAge(5, TimeUnit.DAYS); + + // Creates column family with given GC rule. + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to add a family + ModifyColumnFamiliesRequest columnFamiliesRequest = + ModifyColumnFamiliesRequest.of(tableId).addFamily(COLUMN_FAMILY_1, maxAgeRule); + adminClient.modifyFamilies(columnFamiliesRequest); + System.out.println("Created column family: " + COLUMN_FAMILY_1); + } catch (AlreadyExistsException e) { + System.err.println( + "Failed to create column family with rule, already exists: " + e.getMessage()); + } + // [END bigtable_create_family_gc_max_age] + } + + /** Demonstrates how to create a new instance of the VersionRule. */ + public void addFamilyWithMaxVersionsRule() { + System.out.printf("%nCreating column family %s with max versions GC rule%n", COLUMN_FAMILY_2); + // [START bigtable_create_family_gc_max_versions] + // Creates a column family with GC policy : most recent N versions + // where 1 = most recent version + + // Defines the GC policy to retain only the most recent 2 versions. + VersionRule versionRule = GCRULES.maxVersions(2); + + // Creates column family with given GC rule. + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to add a family + ModifyColumnFamiliesRequest columnFamiliesRequest = + ModifyColumnFamiliesRequest.of(tableId).addFamily(COLUMN_FAMILY_2, versionRule); + adminClient.modifyFamilies(columnFamiliesRequest); + System.out.println("Created column family: " + COLUMN_FAMILY_2); + } catch (AlreadyExistsException e) { + System.err.println( + "Failed to create column family with rule, already exists: " + e.getMessage()); + } + // [END bigtable_create_family_gc_max_versions] + } + + /** Demonstrates how to create a new instance of the UnionRule. */ + public void addFamilyWithUnionRule() { + System.out.printf("%nCreating column family %s with union GC rule%n", COLUMN_FAMILY_3); + // [START bigtable_create_family_gc_union] + // Creates a column family with GC policy to drop data that matches at least one condition. + + // Defines a list of GC rules to drop cells older than 5 days OR not the most recent + // version. + UnionRule unionRule = + GCRULES.union().rule(GCRULES.maxAge(5, TimeUnit.DAYS)).rule(GCRULES.maxVersions(1)); + + // Creates column family with given GC rule. + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to add a family + ModifyColumnFamiliesRequest columnFamiliesRequest = + ModifyColumnFamiliesRequest.of(tableId).addFamily(COLUMN_FAMILY_3, unionRule); + adminClient.modifyFamilies(columnFamiliesRequest); + System.out.println("Created column family: " + COLUMN_FAMILY_3); + } catch (AlreadyExistsException e) { + System.err.println( + "Failed to create column family with rule, already exists: " + e.getMessage()); + } + // [END bigtable_create_family_gc_union] + } + + /** Demonstrates how to create a new instance of the IntersectionRule. */ + public void addFamilyWithIntersectionRule() { + System.out.printf("%nCreating column family %s with intersection GC rule%n", COLUMN_FAMILY_4); + // [START bigtable_create_family_gc_intersection] + // Creates a column family with GC policy to drop data that matches all conditions. + + // Defines a GC rule to drop cells older than 5 days AND older than the most recent 2 versions. + DurationRule maxAgeRule = GCRULES.maxAge(5, TimeUnit.DAYS); + VersionRule versionRule = GCRULES.maxVersions(2); + IntersectionRule intersectionRule = GCRULES.intersection().rule(maxAgeRule).rule(versionRule); + + // Creates column family with given GC rule. + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to add a family + ModifyColumnFamiliesRequest columnFamiliesRequest = + ModifyColumnFamiliesRequest.of(tableId).addFamily(COLUMN_FAMILY_4, intersectionRule); + adminClient.modifyFamilies(columnFamiliesRequest); + System.out.println("Created column family: " + COLUMN_FAMILY_4); + } catch (AlreadyExistsException e) { + System.err.println( + "Failed to create column family with rule, already exists: " + e.getMessage()); + } + // [END bigtable_create_family_gc_intersection] + } + + /** Demonstrates how to create a nested rule using the IntersectionRule and UnionRule. */ + public void addFamilyWithNestedRule() { + System.out.printf("%nCreating column family %s with a nested GC rule%n", COLUMN_FAMILY_5); + // [START bigtable_create_family_gc_nested] + // Creates a nested GC rule: + // Drop cells that are either older than the 10 recent versions + // OR + // Drop cells that are older than a month AND older than the 2 recent versions + VersionRule versionRule1 = GCRULES.maxVersions(10); + VersionRule versionRule2 = GCRULES.maxVersions(2); + DurationRule maxAgeRule = GCRULES.maxAge(30, TimeUnit.DAYS); + IntersectionRule intersectionRule = GCRULES.intersection().rule(maxAgeRule).rule(versionRule2); + UnionRule unionRule = GCRULES.union().rule(intersectionRule).rule(versionRule1); + + // Creates column family with given GC rule. + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to add a family + ModifyColumnFamiliesRequest columnFamiliesRequest = + ModifyColumnFamiliesRequest.of(tableId).addFamily(COLUMN_FAMILY_5, unionRule); + adminClient.modifyFamilies(columnFamiliesRequest); + System.out.println("Created column family: " + COLUMN_FAMILY_5); + } catch (AlreadyExistsException e) { + System.err.println( + "Failed to create column family with rule, already exists: " + e.getMessage()); + } + // [END bigtable_create_family_gc_nested] + } + + /** Demonstrates how to list a table's column families. */ + public void listColumnFamilies() { + System.out.println("\nPrinting ID and GC Rule for all column families"); + // [START bigtable_list_column_families] + // Lists all families in the table with GC rules. + try { + Table table = adminClient.getTable(tableId); + Collection columnFamilies = table.getColumnFamilies(); + for (ColumnFamily columnFamily : columnFamilies) { + System.out.printf( + "Column family: %s%nGC Rule: %s%n", + columnFamily.getId(), columnFamily.getGCRule().toString()); + } + } catch (NotFoundException e) { + System.err.println( + "Failed to list column families from a non-existent table: " + e.getMessage()); + } + // [END bigtable_list_column_families] + } + + /** Demonstrates how to modify a column family's rule. */ + public void modifyColumnFamilyRule() { + System.out.printf("%nUpdating column family %s GC rule%n", COLUMN_FAMILY_1); + // [START bigtable_update_gc_rule] + // Updates the column family metadata to update the GC rule. + // Updates a column family GC rule. + VersionRule versionRule = GCRULES.maxVersions(1); + try { + // ModifyColumnFamiliesRequest can be used both for adding and modifying families, here it is + // being used to modify a family + // Updates column family with given GC rule. + ModifyColumnFamiliesRequest updateRequest = + ModifyColumnFamiliesRequest.of(tableId).updateFamily(COLUMN_FAMILY_1, versionRule); + adminClient.modifyFamilies(updateRequest); + System.out.printf("Column family %s GC rule updated%n", COLUMN_FAMILY_1); + } catch (NotFoundException e) { + System.err.println("Failed to modify a non-existent column family: " + e.getMessage()); + } + // [END bigtable_update_gc_rule] + } + + /** Demonstrates how to print the modified column family. */ + public void printModifiedColumnFamily() { + System.out.printf("%nPrint updated GC rule for column family %s%n", COLUMN_FAMILY_1); + // [START bigtable_family_get_gc_rule] + try { + Table table = adminClient.getTable(tableId); + Collection columnFamilies = table.getColumnFamilies(); + for (ColumnFamily columnFamily : columnFamilies) { + if (columnFamily.getId().equals(COLUMN_FAMILY_1)) { + System.out.printf( + "Column family: %s%nGC Rule: %s%n", + columnFamily.getId(), columnFamily.getGCRule().toString()); + } + } + } catch (NotFoundException e) { + System.err.println("Failed to print a non-existent column family: " + e.getMessage()); + } + // [END bigtable_family_get_gc_rule] + } + + /** Demonstrates how to delete a column family. */ + public void deleteColumnFamily() { + System.out.println("\nDelete column family: " + COLUMN_FAMILY_2); + // [START bigtable_delete_family] + // Deletes a column family. + try { + ModifyColumnFamiliesRequest deleted = + ModifyColumnFamiliesRequest.of(tableId).dropFamily(COLUMN_FAMILY_2); + adminClient.modifyFamilies(deleted); + System.out.printf("Column family %s deleted successfully%n", COLUMN_FAMILY_2); + } catch (NotFoundException e) { + System.err.println("Failed to delete a non-existent column family: " + e.getMessage()); + } + // [END bigtable_delete_family] + } + + /** Demonstrates how to delete a table. */ + public void deleteTable() { + // [START bigtable_delete_table] + // Deletes the entire table. + System.out.println("\nDelete table: " + tableId); + try { + adminClient.deleteTable(tableId); + System.out.printf("Table: %s deleted successfully%n", tableId); + } catch (NotFoundException e) { + System.err.println("Failed to delete a non-existent table: " + e.getMessage()); + } + // [END bigtable_delete_table] + } +} diff --git a/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java b/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java new file mode 100644 index 00000000000..522a99e0148 --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import com.google.cloud.bigtable.data.v2.models.Row; +import java.io.IOException; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.AssumptionViolatedException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** Integration tests for {@link HelloWorld} */ +public class HelloWorldTest { + + private static final String INSTANCE_PROPERTY_NAME = "BIGTABLE_TESTING_INSTANCE"; + private static final String TABLE_PREFIX = "table"; + private static String tableId; + private static BigtableDataClient dataClient; + private static BigtableTableAdminClient adminClient; + private static String projectId; + private static String instanceId; + private HelloWorld helloWorld; + + private static String requireEnv(String varName) { + assertNotNull( + System.getenv(varName), + "System property '%s' is required to perform these tests.".format(varName)); + return System.getenv(varName); + } + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + instanceId = requireEnv(INSTANCE_PROPERTY_NAME); + if (projectId == null || instanceId == null) { + dataClient = null; + adminClient = null; + return; + } + BigtableDataSettings settings = + BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId).build(); + dataClient = BigtableDataClient.create(settings); + BigtableTableAdminSettings adminSettings = + BigtableTableAdminSettings.newBuilder() + .setProjectId(projectId) + .setInstanceId(instanceId) + .build(); + adminClient = BigtableTableAdminClient.create(adminSettings); + } + + @AfterClass + public static void afterClass() throws Exception { + garbageCollect(); + dataClient.close(); + adminClient.close(); + } + + @Before + public void setup() throws IOException { + tableId = generateTableId(); + helloWorld = new HelloWorld(projectId, instanceId, tableId); + adminClient.createTable(CreateTableRequest.of(tableId).addFamily("cf1")); + } + + @After + public void after() { + if (adminClient.exists(tableId)) { + adminClient.deleteTable(tableId); + } + } + + @Test + public void testCreateAndDeleteTable() throws IOException { + // Creates a table. + String testTable = generateTableId(); + HelloWorld testHelloWorld = new HelloWorld(projectId, instanceId, testTable); + testHelloWorld.createTable(); + assertTrue(adminClient.exists(testTable)); + + // Deletes a table. + testHelloWorld.deleteTable(); + assertTrue(!adminClient.exists(testTable)); + } + + @Test + public void testWriteToTable() { + // Writes to a table. + helloWorld.writeToTable(); + Row row = dataClient.readRow(tableId, "rowKey0"); + assertNotNull(row); + } + + // TODO: add test for helloWorld.readSingleRow() + // TODO: add test for helloWorld.readTable() + + @Test + public void testRunDoesNotFail() throws Exception { + helloWorld.run(); + } + + private String generateTableId() { + return String.format( + "%s-%016x-%x", TABLE_PREFIX, System.currentTimeMillis(), new Random().nextLong()); + } + + private static void garbageCollect() { + Pattern timestampPattern = Pattern.compile(TABLE_PREFIX + "-([0-9a-f]+)-([0-9a-f]+)"); + for (String tableId : adminClient.listTables()) { + Matcher matcher = timestampPattern.matcher(tableId); + if (!matcher.matches()) { + continue; + } + String timestampStr = matcher.group(1); + long timestamp = Long.parseLong(timestampStr, 16); + if (System.currentTimeMillis() - timestamp < TimeUnit.MINUTES.toMillis(15)) { + continue; + } + System.out.println("\nGarbage collecting orphaned table: " + tableId); + adminClient.deleteTable(tableId); + } + } +} diff --git a/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java b/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java new file mode 100644 index 00000000000..b7bcee7d3aa --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.api.gax.rpc.NotFoundException; +import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableInstanceAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.Cluster; +import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest; +import com.google.cloud.bigtable.admin.v2.models.Instance; +import com.google.cloud.bigtable.admin.v2.models.Instance.Type; +import com.google.cloud.bigtable.admin.v2.models.StorageType; +import java.io.IOException; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.AssumptionViolatedException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** Integration tests for {@link InstanceAdminExample} */ +public class InstanceAdminExampleTest { + + private static final String ID_PREFIX = "instanceadmin"; + private static final String CLUSTER = "cluster"; + private static String projectId; + private static BigtableInstanceAdminClient adminClient; + private String clusterId; + private String instanceId; + private InstanceAdminExample instanceAdmin; + + private static String requireEnv(String varName) { + assertNotNull( + System.getenv(varName), + "System property '%s' is required to perform these tests.".format(varName)); + return System.getenv(varName); + } + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + if (projectId == null) { + adminClient = null; + return; + } + BigtableInstanceAdminSettings instanceAdminSettings = + BigtableInstanceAdminSettings.newBuilder().setProjectId(projectId).build(); + adminClient = BigtableInstanceAdminClient.create(instanceAdminSettings); + } + + @AfterClass + public static void afterClass() { + garbageCollect(); + adminClient.close(); + } + + @Before + public void setup() throws IOException { + instanceId = generateId(); + clusterId = generateId(); + instanceAdmin = new InstanceAdminExample(projectId, instanceId, clusterId); + adminClient.createInstance( + CreateInstanceRequest.of(instanceId) + .addCluster(clusterId, "us-central1-f", 3, StorageType.SSD) + .setType(Type.PRODUCTION) + .addLabel("example", "instance_admin")); + } + + @After + public void after() { + if (adminClient.exists(instanceId)) { + adminClient.deleteInstance(instanceId); + } + } + + @Test + public void testCreateAndDeleteInstance() throws IOException { + // Creates an instance. + String testInstance = generateId(); + String testCluster = generateId(); + InstanceAdminExample testInstanceAdmin = + new InstanceAdminExample(projectId, testInstance, testCluster); + testInstanceAdmin.createProdInstance(); + assertTrue(adminClient.exists(testInstance)); + + // Deletes an instance. + testInstanceAdmin.deleteInstance(); + assertFalse(adminClient.exists(testInstance)); + } + + @Test + public void testGetInstance() { + // Gets an instance. + Instance instance = instanceAdmin.getInstance(); + assertNotNull(instance); + } + + @Test(expected = NotFoundException.class) + public void testAddAndDeleteCluster() { + // Adds a cluster. + instanceAdmin.addCluster(); + Cluster cluster = adminClient.getCluster(instanceId, CLUSTER); + assertNotNull(cluster); + + // Deletes a cluster. + instanceAdmin.deleteCluster(); + adminClient.getCluster(instanceId, CLUSTER); + } + + // TODO: add test for instanceAdmin.listInstances() + // TODO: and test for instanceAdmin.listClusters() + + @Test + public void testRunDoesNotFail() { + instanceAdmin.run(); + } + + private static String generateId() { + return String.format("%s-%x", ID_PREFIX, new Random().nextInt()); + } + + private static void garbageCollect() { + Pattern timestampPattern = Pattern.compile(ID_PREFIX + "-([0-9a-f]+)"); + System.out.println(); + for (Instance instance : adminClient.listInstances()) { + Matcher matcher = timestampPattern.matcher(instance.getId()); + if (!matcher.matches()) { + continue; + } + System.out.println("Garbage collecting orphaned table: " + instance); + adminClient.deleteInstance(instance.getId()); + } + } +} diff --git a/bigtable/src/test/java/com/m/examples/bigtable/QuickstartTest.java b/bigtable/src/test/java/com/m/examples/bigtable/QuickstartTest.java new file mode 100644 index 00000000000..929506859ce --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/QuickstartTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2019 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.m.examples.bigtable; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.data.v2.BigtableDataClient; +import com.google.cloud.bigtable.data.v2.BigtableDataSettings; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.AssumptionViolatedException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * Integration tests for {@link Quickstart} + */ +public class QuickstartTest { + + private static final String INSTANCE_PROPERTY_NAME = "BIGTABLE_TESTING_INSTANCE"; + private static final String TABLE_ID = "quickstart-table"; + private static String projectId; + private static String instanceId; + private ByteArrayOutputStream bout; + + private static String requireEnv(String varName) { + assertNotNull( + System.getenv(varName), + "System property '%s' is required to perform these tests.".format(varName)); + return System.getenv(varName); + } + + @BeforeClass + public static void beforeClass() { + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + instanceId = requireEnv(INSTANCE_PROPERTY_NAME); + } + + @Before + public void setupStream() { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @Test + public void testQuickstart() { + try { + Quickstart.quickstart(projectId, instanceId, TABLE_ID); + } catch (Exception e) { + System.out.println("Failed to run quickstart."); + System.out.println(e); + } + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Reading a single row by row key")); + assertThat(output, CoreMatchers.containsString("Row: r1")); + assertThat( + output, CoreMatchers.containsString("Family: cf1 Qualifier: c1 Value: quickstart")); + } +} diff --git a/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java b/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java new file mode 100644 index 00000000000..51ed37cf053 --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java @@ -0,0 +1,227 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.m.examples.bigtable; + +import static com.google.cloud.bigtable.admin.v2.models.GCRules.GCRULES; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminClient; +import com.google.cloud.bigtable.admin.v2.BigtableTableAdminSettings; +import com.google.cloud.bigtable.admin.v2.models.ColumnFamily; +import com.google.cloud.bigtable.admin.v2.models.CreateTableRequest; +import com.google.cloud.bigtable.admin.v2.models.GCRules.DurationRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.GCRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.IntersectionRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.UnionRule; +import com.google.cloud.bigtable.admin.v2.models.GCRules.VersionRule; +import java.io.IOException; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.AssumptionViolatedException; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** Integration tests for {@link TableAdminExample} */ +public class TableAdminExampleTest { + + private static final String INSTANCE_PROPERTY_NAME = "BIGTABLE_TESTING_INSTANCE"; + private static final String TABLE_PREFIX = "table"; + private static BigtableTableAdminClient adminClient; + private static String instanceId; + private static String projectId; + private String tableId; + private TableAdminExample tableAdmin; + + private static String requireEnv(String varName) { + assertNotNull( + System.getenv(varName), + "System property '%s' is required to perform these tests.".format(varName)); + return System.getenv(varName); + } + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + instanceId = requireEnv(INSTANCE_PROPERTY_NAME); + if (projectId == null || instanceId == null) { + adminClient = null; + return; + } + BigtableTableAdminSettings adminSettings = + BigtableTableAdminSettings.newBuilder() + .setInstanceId(instanceId) + .setProjectId(projectId) + .build(); + adminClient = BigtableTableAdminClient.create(adminSettings); + } + + @AfterClass + public static void afterClass() { + garbageCollect(); + adminClient.close(); + } + + @Before + public void setup() throws IOException { + tableId = generateTableId(); + tableAdmin = new TableAdminExample(projectId, instanceId, tableId); + adminClient.createTable(CreateTableRequest.of(tableId).addFamily("cf")); + } + + @After + public void after() { + if (adminClient.exists(tableId)) { + adminClient.deleteTable(tableId); + } + } + + @Test + public void testCreateAndDeleteTable() throws IOException { + // Creates a table. + String testTable = generateTableId(); + TableAdminExample testTableAdmin = new TableAdminExample(projectId, instanceId, testTable); + testTableAdmin.createTable(); + assertTrue(adminClient.exists(testTable)); + + // Deletes a table. + testTableAdmin.deleteTable(); + assertFalse(adminClient.exists(testTable)); + } + + @Test + public void testCreateMaxAgeRuleAndModifyAndPrintColumnFamily() { + // Max age rule + tableAdmin.addFamilyWithMaxAgeRule(); + DurationRule maxAgeCondition = GCRULES.maxAge(5, TimeUnit.DAYS); + boolean maxAgeRule = ruleCheck(maxAgeCondition); + assertTrue(maxAgeRule); + + // Modifies cf1. + tableAdmin.modifyColumnFamilyRule(); + GCRule modifiedRule = GCRULES.maxVersions(1); + boolean maxVersionRule = ruleCheck(modifiedRule); + assertTrue(maxVersionRule); + } + + @Test + public void testCreateMaxVersionsRuleAndDeleteColumnFamily() { + // Max versions rule + tableAdmin.addFamilyWithMaxVersionsRule(); + VersionRule maxVersionCondition = GCRULES.maxVersions(2); + boolean maxVersionRule = ruleCheck(maxVersionCondition); + assertTrue(maxVersionRule); + + // Deletes cf2. + tableAdmin.deleteColumnFamily(); + boolean found = true; + List columnFamilies = adminClient.getTable(tableId).getColumnFamilies(); + for (ColumnFamily columnFamily : columnFamilies) { + if (columnFamily.equals("cf2")) { + found = false; + break; + } + } + assertTrue(found); + } + + @Test + public void testCreateUnionRule() { + // Union rule + tableAdmin.addFamilyWithUnionRule(); + DurationRule maxAgeRule = GCRULES.maxAge(5, TimeUnit.DAYS); + VersionRule versionRule = GCRULES.maxVersions(1); + UnionRule unionCondition = GCRULES.union().rule(maxAgeRule).rule(versionRule); + boolean unionRule = ruleCheck(unionCondition); + assertTrue(unionRule); + } + + @Test + public void testCreateIntersectionRule() { + // Intersection rule + tableAdmin.addFamilyWithIntersectionRule(); + DurationRule maxAgeRule = GCRULES.maxAge(5, TimeUnit.DAYS); + VersionRule versionRule = GCRULES.maxVersions(2); + IntersectionRule intersectionCondition = + GCRULES.intersection().rule(maxAgeRule).rule(versionRule); + boolean intersectionRule = ruleCheck(intersectionCondition); + assertTrue(intersectionRule); + } + + @Test + public void testCreateNestedRule() { + // Nested rule + tableAdmin.addFamilyWithNestedRule(); + VersionRule versionRule = GCRULES.maxVersions(10); + DurationRule maxAgeRule = GCRULES.maxAge(30, TimeUnit.DAYS); + VersionRule versionRule2 = GCRULES.maxVersions(2); + IntersectionRule intersectionRule = GCRULES.intersection().rule(maxAgeRule).rule(versionRule2); + UnionRule nestedCondition = GCRULES.union().rule(intersectionRule).rule(versionRule); + boolean nestedRule = ruleCheck(nestedCondition); + assertTrue(nestedRule); + } + + @Test + public void testRunDoesNotFail() { + tableAdmin.run(); + } + + // TODO: add test for tableAdmin.listAllTables() + // TODO: add test for tableAdmin.getTableMeta() + // TODO: add test for tableAdmin.listColumnFamilies() + + private boolean ruleCheck(GCRule condition) { + boolean found = false; + List columnFamilies = adminClient.getTable(tableId).getColumnFamilies(); + for (ColumnFamily columnFamily : columnFamilies) { + if (columnFamily.getGCRule().equals(condition)) { + found = true; + break; + } + } + return found; + } + + private String generateTableId() { + return String.format( + "%s-%016x-%x", TABLE_PREFIX, System.currentTimeMillis(), new Random().nextLong()); + } + + private static void garbageCollect() { + Pattern timestampPattern = Pattern.compile(TABLE_PREFIX + "-([0-9a-f]+)-([0-9a-f]+)"); + for (String tableId : adminClient.listTables()) { + Matcher matcher = timestampPattern.matcher(tableId); + if (!matcher.matches()) { + continue; + } + String timestampStr = matcher.group(1); + long timestamp = Long.parseLong(timestampStr, 16); + if (System.currentTimeMillis() - timestamp < TimeUnit.MINUTES.toMillis(10)) { + continue; + } + System.out.println("\nGarbage collecting orphaned table: " + tableId); + adminClient.deleteTable(tableId); + } + } +} diff --git a/cdn/signed-urls/pom.xml b/cdn/signed-urls/pom.xml index 83fd86e4b29..24ce4960f63 100644 --- a/cdn/signed-urls/pom.xml +++ b/cdn/signed-urls/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 signedurls diff --git a/cloud-sql/mysql/servlet/pom.xml b/cloud-sql/mysql/servlet/pom.xml index 87abeca4403..a3f7c86130f 100644 --- a/cloud-sql/mysql/servlet/pom.xml +++ b/cloud-sql/mysql/servlet/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/cloud-sql/postgres/servlet/pom.xml b/cloud-sql/postgres/servlet/pom.xml index a3efde77776..31109030657 100644 --- a/cloud-sql/postgres/servlet/pom.xml +++ b/cloud-sql/postgres/servlet/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/compute/cmdline/pom.xml b/compute/cmdline/pom.xml index ed9b7479f09..fb28c1cd3bb 100644 --- a/compute/cmdline/pom.xml +++ b/compute/cmdline/pom.xml @@ -26,7 +26,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/compute/error-reporting/pom.xml b/compute/error-reporting/pom.xml index 8b719a3ae10..db5ad6ea8dd 100644 --- a/compute/error-reporting/pom.xml +++ b/compute/error-reporting/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/compute/mailjet/pom.xml b/compute/mailjet/pom.xml index 6aa7b104e78..9acb0bc7f30 100644 --- a/compute/mailjet/pom.xml +++ b/compute/mailjet/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 @@ -67,6 +67,7 @@ maven-assembly-plugin + 3.1.1 package diff --git a/compute/pom.xml b/compute/pom.xml deleted file mode 100644 index becce02d9c5..00000000000 --- a/compute/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - 1.0.0 - - com.google.cloud - compute - pom - - - - doc-samples - com.google.cloud - 1.0.0 - .. - - - - cmdline - error-reporting - mailjet - sendgrid - signed-metadata - - - diff --git a/compute/sendgrid/pom.xml b/compute/sendgrid/pom.xml index 6b050a74c1e..2f77c47c832 100644 --- a/compute/sendgrid/pom.xml +++ b/compute/sendgrid/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/compute/signed-metadata/pom.xml b/compute/signed-metadata/pom.xml index 7e16b8dae68..f1849a87a33 100644 --- a/compute/signed-metadata/pom.xml +++ b/compute/signed-metadata/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/container-registry/container-analysis/pom.xml b/container-registry/container-analysis/pom.xml index a44c48d1826..fc3b9e98255 100644 --- a/container-registry/container-analysis/pom.xml +++ b/container-registry/container-analysis/pom.xml @@ -17,7 +17,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateNote.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateNote.java new file mode 100644 index 00000000000..871f65c60ee --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateNote.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_create_note] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Note; +import io.grafeas.v1beta1.vulnerability.Severity; +import io.grafeas.v1beta1.vulnerability.Vulnerability; +import io.grafeas.v1beta1.vulnerability.Vulnerability.Detail; +import java.io.IOException; +import java.lang.InterruptedException; + + +public class CreateNote { + + // Creates and returns a new Note + public static Note createNote(String noteId, String projectId) + throws IOException, InterruptedException { + // String noteId = "my-note"; + // String projectId = "my-project-id"; + final String projectName = ProjectName.format(projectId); + + Note.Builder noteBuilder = Note.newBuilder(); + // Associate the Note with the metadata type + // https://cloud.google.com/container-registry/docs/container-analysis#supported_metadata_types + // Here, we use the type "vulnerability" + Vulnerability.Builder vulBuilder = Vulnerability.newBuilder(); + noteBuilder.setVulnerability(vulBuilder); + // Set additional information specific to your new vulnerability note + Detail.Builder detailsBuilder = Detail.newBuilder(); + detailsBuilder.setDescription("my new vulnerability note"); + vulBuilder.setSeverity(Severity.LOW); + vulBuilder.addDetails(detailsBuilder); + // Build the Note object + Note newNote = noteBuilder.build(); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + Note result = client.createNote(projectName, noteId, newNote); + return result; + } +} +// [END containeranalysis_create_note] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateOccurrence.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateOccurrence.java new file mode 100644 index 00000000000..ac87f3487ea --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateOccurrence.java @@ -0,0 +1,60 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_create_occurrence] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.NoteName; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import io.grafeas.v1beta1.Resource; +import io.grafeas.v1beta1.vulnerability.Details; +import java.io.IOException; +import java.lang.InterruptedException; + +public class CreateOccurrence { + // Creates and returns a new Occurrence associated with an existing Note + public static Occurrence createOccurrence(String resourceUrl, String noteId, + String occProjectId, String noteProjectId) throws IOException, InterruptedException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String noteId = "my-note"; + // String occProjectId = "my-project-id"; + // String noteProjectId = "my-project-id"; + final NoteName noteName = NoteName.of(noteProjectId, noteId); + final String occProjectName = ProjectName.format(occProjectId); + + Occurrence.Builder occBuilder = Occurrence.newBuilder(); + occBuilder.setNoteName(noteName.toString()); + // Associate the Occurrence with the metadata type (should match the parent Note's type) + // https://cloud.google.com/container-registry/docs/container-analysis#supported_metadata_types + // Here, we use the type "vulnerability" + Details.Builder detailsBuilder = Details.newBuilder(); + occBuilder.setVulnerability(detailsBuilder); + // Attach the occurrence to the associated image uri + Resource.Builder resourceBuilder = Resource.newBuilder(); + resourceBuilder.setUri(resourceUrl); + occBuilder.setResource(resourceBuilder); + Occurrence newOcc = occBuilder.build(); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + Occurrence result = client.createOccurrence(occProjectName, newOcc); + return result; + } +} +// [END containeranalysis_create_occurrence] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteNote.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteNote.java new file mode 100644 index 00000000000..9a4f92a421d --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteNote.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_delete_note] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.NoteName; +import java.io.IOException; +import java.lang.InterruptedException; + +public class DeleteNote { + // Deletes an existing Note from the server + public static void deleteNote(String noteId, String projectId) + throws IOException, InterruptedException { + // String noteId = "my-note"; + // String projectId = "my-project-id"; + final NoteName noteName = NoteName.of(projectId, noteId); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + client.deleteNote(noteName); + } +} +// [END containeranalysis_delete_note] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteOccurrence.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteOccurrence.java new file mode 100644 index 00000000000..47abfa9a7c2 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteOccurrence.java @@ -0,0 +1,39 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_delete_occurrence] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.OccurrenceName; +import java.io.IOException; +import java.lang.InterruptedException; + +public class DeleteOccurrence { + // Deletes an existing Occurrence from the server + public static void deleteOccurrence(String occurrenceId, String projectId) + throws IOException, InterruptedException { + // String occurrenceId = "123-456-789"; + // String projectId = "my-project-id"; + final OccurrenceName occurrenceName = OccurrenceName.of(projectId, occurrenceId); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + client.deleteOccurrence(occurrenceName); + } +} +// [END containeranalysis_delete_occurrence] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetDiscoveryInfo.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetDiscoveryInfo.java new file mode 100644 index 00000000000..4203a3a60d3 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetDiscoveryInfo.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_discovery_info] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import java.io.IOException; +import java.lang.InterruptedException; + +public class GetDiscoveryInfo { + // Retrieves and prints the Discovery Occurrence created for a specified image + // The Discovery Occurrence contains information about the initial scan on the image + public static void getDiscoveryInfo(String resourceUrl, String projectId) + throws IOException, InterruptedException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String projectId = "my-project-id"; + String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + resourceUrl + "\""; + final String projectName = ProjectName.format(projectId); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { + System.out.println(o); + } + } +} +// [END containeranalysis_discovery_info] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetNote.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetNote.java new file mode 100644 index 00000000000..23aea0b28a0 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetNote.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_get_note] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.NoteName; +import io.grafeas.v1beta1.Note; +import java.io.IOException; +import java.lang.InterruptedException; + +public class GetNote { + // Retrieves and prints a specified Note from the server + public static Note getNote(String noteId, String projectId) + throws IOException, InterruptedException { + // String noteId = "my-note"; + // String projectId = "my-project-id"; + final NoteName noteName = NoteName.of(projectId, noteId); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + Note n = client.getNote(noteName); + System.out.println(n); + return n; + } +} +// [END containeranalysis_get_note] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetOccurrence.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetOccurrence.java new file mode 100644 index 00000000000..57be93557b3 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetOccurrence.java @@ -0,0 +1,42 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_get_occurrence] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.OccurrenceName; +import io.grafeas.v1beta1.Occurrence; +import java.io.IOException; +import java.lang.InterruptedException; + +public class GetOccurrence { + // Retrieves and prints a specified Occurrence from the server + public static Occurrence getOccurrence(String occurrenceId, String projectId) + throws IOException, InterruptedException { + // String occurrenceId = "123-456-789"; + // String projectId = "my-project-id"; + final OccurrenceName occurrenceName = OccurrenceName.of(projectId, occurrenceId); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + Occurrence occ = client.getOccurrence(occurrenceName); + System.out.println(occ); + return occ; + } +} +// [END containeranalysis_get_occurrence] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/HighVulnerabilitiesForImage.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/HighVulnerabilitiesForImage.java new file mode 100644 index 00000000000..2e99cee0f91 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/HighVulnerabilitiesForImage.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_filter_vulnerability_occurrences] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import io.grafeas.v1beta1.vulnerability.Severity; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +public class HighVulnerabilitiesForImage { + // Retrieve a list of vulnerability occurrences with a severity level of 'HIGH' or greater + public static List findHighSeverityVulnerabilitiesForImage(String resourceUrl, + String projectId) throws IOException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String projectId = "my-project-id"; + final String projectName = ProjectName.format(projectId); + String filterStr = String.format("kind=\"VULNERABILITY\" AND resourceUrl=\"%s\"", resourceUrl); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + LinkedList vulnerabilitylist = new LinkedList(); + for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { + Severity severity = o.getVulnerability().getSeverity(); + if (severity == Severity.HIGH || severity == Severity.CRITICAL) { + vulnerabilitylist.add(o); + } + } + return vulnerabilitylist; + } +} +// [END containeranalysis_filter_vulnerability_occurrences] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForImage.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForImage.java new file mode 100644 index 00000000000..57130203425 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForImage.java @@ -0,0 +1,48 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_occurrences_for_image] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import java.io.IOException; +import java.lang.InterruptedException; + +public class OccurrencesForImage { + // Retrieves all the Occurrences associated with a specified image + // Here, all Occurrences are simply printed and counted + public static int getOccurrencesForImage(String resourceUrl, String projectId) + throws IOException, InterruptedException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String projectId = "my-project-id"; + final String projectName = ProjectName.format(projectId); + final String filterStr = String.format("resourceUrl=\"%s\"", resourceUrl); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + int i = 0; + for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { + // Write custom code to process each Occurrence here + System.out.println(o.getName()); + i = i + 1; + } + return i; + } +} +// [END containeranalysis_occurrences_for_image] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForNote.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForNote.java new file mode 100644 index 00000000000..7e6cbce9d8a --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForNote.java @@ -0,0 +1,54 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_occurrences_for_note] +import static java.lang.Thread.sleep; + +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.NoteName; +import io.grafeas.v1beta1.ListNoteOccurrencesRequest; +import io.grafeas.v1beta1.Occurrence; +import java.io.IOException; +import java.lang.InterruptedException; + +public class OccurrencesForNote { + // Retrieves all the Occurrences associated with a specified Note + // Here, all Occurrences are printed and counted + public static int getOccurrencesForNote(String noteId, String projectId) + throws IOException, InterruptedException { + // String noteId = "my-note"; + // String projectId = "my-project-id"; + final NoteName noteName = NoteName.of(projectId, noteId); + + ListNoteOccurrencesRequest request = ListNoteOccurrencesRequest.newBuilder() + .setName(noteName.toString()) + .build(); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + int i = 0; + for (Occurrence o : client.listNoteOccurrences(request).iterateAll()) { + // Write custom code to process each Occurrence here + System.out.println(o.getName()); + i = i + 1; + } + return i; + } +} +// [END containeranalysis_occurrences_for_note] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PollDiscoveryOccurrenceFinished.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PollDiscoveryOccurrenceFinished.java new file mode 100644 index 00000000000..040fec7de00 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PollDiscoveryOccurrenceFinished.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_poll_discovery_occurrence_finished]i +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import io.grafeas.v1beta1.discovery.Discovered.AnalysisStatus; +import java.io.IOException; +import java.lang.InterruptedException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class PollDiscoveryOccurrenceFinished { + // Repeatedly query the Container Analysis API for the latest discovery occurrence until it is + // either in a terminal state, or the timeout value has been exceeded + public static Occurrence pollDiscoveryOccurrenceFinished(String resourceUrl, String projectId, + long timeoutSeconds) throws IOException, TimeoutException, InterruptedException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String projectId = "my-project-id"; + // long timeoutSeconds = 30; + final String projectName = ProjectName.format(projectId); + long deadline = System.currentTimeMillis() + timeoutSeconds * 1000; + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + + // find the discovery occurrence using a filter string + Occurrence discoveryOccurrence = null; + // vulbnerability discovery occurrences are always associated with the + // PACKAGE_VULNERABILITY note in the "goog-analysis" GCP project + String filter = String.format("resourceUrl=\"%s\" AND noteProjectId=\"%s\" AND noteId=\"%s\"", + resourceUrl, "goog-analysis", "PACKAGE_VULNERABILITY"); + // [END containeranalysis_poll_discovery_occurrence_finished] + // the above filter isn't testable, since it looks for occurrences in a locked down project + // fall back to a more permissive filter for testing + filter = String.format("kind=\"DISCOVERY\" AND resourceUrl=\"%s\"", resourceUrl); + // [START containeranalysis_poll_discovery_occurrence_finished] + while (discoveryOccurrence == null) { + for (Occurrence o : client.listOccurrences(projectName, filter).iterateAll()) { + if (o.getDiscovered() != null) { + // there should be only one valid discovery occurrence returned by the given filter + discoveryOccurrence = o; + } + } + TimeUnit.SECONDS.sleep(1); + // check for timeout + if (System.currentTimeMillis() > deadline) { + throw new TimeoutException("discovery occurrence not found"); + } + } + + // wait for discovery occurrence to enter a terminal state + AnalysisStatus status = AnalysisStatus.PENDING; + while (status != AnalysisStatus.FINISHED_SUCCESS + && status != AnalysisStatus.FINISHED_FAILED + && status != AnalysisStatus.FINISHED_UNSUPPORTED) { + // update the occurrence state + discoveryOccurrence = client.getOccurrence(discoveryOccurrence.getName()); + status = discoveryOccurrence.getDiscovered().getDiscovered().getAnalysisStatus(); + TimeUnit.SECONDS.sleep(1); + // check for timeout + if (System.currentTimeMillis() > deadline) { + throw new TimeoutException("discovery occurrence not in terminal state"); + } + } + return discoveryOccurrence; + } +} +// [END containeranalysis_poll_discovery_occurrence_finished] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Samples.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Samples.java deleted file mode 100644 index c5c69149d4d..00000000000 --- a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Samples.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2018 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.containeranalysis; - -import static java.lang.Thread.sleep; - -import com.google.cloud.devtools.containeranalysis.v1beta1.ContainerAnalysisV1Beta1Client; -import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; -import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client.ListNoteOccurrencesPagedResponse; -import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client.ListOccurrencesPagedResponse; -import com.google.cloud.pubsub.v1.AckReplyConsumer; -import com.google.cloud.pubsub.v1.MessageReceiver; -import com.google.cloud.pubsub.v1.Subscriber; -import com.google.cloud.pubsub.v1.SubscriptionAdminClient; -import com.google.containeranalysis.v1beta1.NoteName; -import com.google.containeranalysis.v1beta1.ProjectName; -import com.google.pubsub.v1.ProjectSubscriptionName; -import com.google.pubsub.v1.ProjectTopicName; -import com.google.pubsub.v1.PubsubMessage; -import com.google.pubsub.v1.PushConfig; -import com.google.pubsub.v1.Subscription; -import io.grafeas.v1beta1.ListNoteOccurrencesRequest; -import io.grafeas.v1beta1.ListOccurrencesRequest; -import io.grafeas.v1beta1.Note; -import io.grafeas.v1beta1.Occurrence; -import io.grafeas.v1beta1.Resource; -import io.grafeas.v1beta1.UpdateNoteRequest; -import io.grafeas.v1beta1.UpdateOccurrenceRequest; -import io.grafeas.v1beta1.vulnerability.Details; -import io.grafeas.v1beta1.vulnerability.Severity; -import io.grafeas.v1beta1.vulnerability.Vulnerability; -import io.grpc.StatusRuntimeException; -import java.io.IOException; -import java.lang.InterruptedException; - -/** - * API usage samples - */ -public class Samples { - - // [START create_note] - /** - * Creates and returns a new vulnerability Note - * @param client The Grafeas client used to perform the API requests. - * @param noteId A user-specified identifier for the Note. - * @param projectId the GCP project the Note will be created under - * @return the newly created Note object - */ - public static Note createNote(GrafeasV1Beta1Client client, String noteId, String projectId) { - Note.Builder noteBuilder = Note.newBuilder(); - Vulnerability.Builder vulBuilder = Vulnerability.newBuilder(); - // Details about the your vulnerability can be added here - // Example: vulBuilder.setSeverity(Severity.CRITICAL); - noteBuilder.setVulnerability(vulBuilder); - Note newNote = noteBuilder.build(); - - final String projectName = ProjectName.format(projectId); - return client.createNote(projectName, noteId, newNote); - } - // [END create_note] - - - // [START create_occurrence] - /** - * Creates and returns a new Occurrence of a previously created vulnerability Note - * @param client The Grafeas client used to perform the API requests. - * @param imageUrl the Container Registry URL associated with the image - * example: "https://gcr.io/project/image@sha256:foo" - * @param noteId the identifier of the Note associated with this Occurrence - * @param occProjectId the GCP project the Occurrence will be created under - * @param noteProjectId the GCP project the associated Note belongs to - * @return the newly created Occurrence object - */ - public static Occurrence createOccurrence(GrafeasV1Beta1Client client, String imageUrl, - String noteId, String occProjectId, String noteProjectId) { - final NoteName noteName = NoteName.of(noteProjectId, noteId); - final String occProjectName = ProjectName.format(occProjectId); - - Occurrence.Builder occBuilder = Occurrence.newBuilder(); - occBuilder.setNoteName(noteName.toString()); - Details.Builder detailsBuilder = Details.newBuilder(); - // Details about the vulnerability instance can be added here - occBuilder.setVulnerability(detailsBuilder); - // Attach the occurrence to the associated image uri - Resource.Builder resourceBuilder = Resource.newBuilder(); - resourceBuilder.setUri(imageUrl); - occBuilder.setResource(resourceBuilder); - Occurrence newOcc = occBuilder.build(); - return client.createOccurrence(occProjectName, newOcc); - } - // [END create_occurrence] - - // [START update_note] - /** - * Pushes an update to a Note that already exists on the server - * @param client The Grafeas client used to perform the API requests. - * @param updated a Note object representing the desired updates to push - * @param noteId the identifier of the existing Note - * @param projectId the GCP project the Note belongs to - */ - public static Note updateNote(GrafeasV1Beta1Client client, Note updated, String noteId, - String projectId) { - final NoteName noteName = NoteName.of(projectId, noteId); - UpdateNoteRequest request = UpdateNoteRequest.newBuilder() - .setName(noteName.toString()) - .setNote(updated) - .build(); - return client.updateNote(request); - } - // [END update_note] - - // [START update_occurrence] - /** - * Pushes an update to an Occurrence that already exists on the server - * @param client The Grafeas client used to perform the API requests. - * @param occurrenceName the name of the Occurrence to delete. - * format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]" - * @param updated an Occurrence object representing the desired updates to push - */ - public static Occurrence updateOccurrence(GrafeasV1Beta1Client client, String occurrenceName, - Occurrence updated) { - UpdateOccurrenceRequest request = UpdateOccurrenceRequest.newBuilder() - .setName(occurrenceName) - .setOccurrence(updated) - .build(); - return client.updateOccurrence(request); - } - // [END update_occurrence] - - // [START delete_note] - /** - * Deletes an existing Note from the server - * @param client The Grafeas client used to perform the API requests. - * @param noteId the identifier of the Note to delete - * @param projectId the GCP project the Note belongs to - */ - public static void deleteNote(GrafeasV1Beta1Client client, String noteId, String projectId) { - final NoteName noteName = NoteName.of(projectId, noteId); - client.deleteNote(noteName); - } - // [END delete_note] - - // [START delete_occurrence] - /** - * Deletes an existing Occurrence from the server - * @param client The Grafeas client used to perform the API requests. - * @param occurrenceName the name of the Occurrence to delete - * format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]" - */ - public static void deleteOccurrence(GrafeasV1Beta1Client client, String occurrenceName) { - client.deleteOccurrence(occurrenceName); - } - // [END delete_occurrence] - - - // [START get_occurrence] - /** - * Retrieves and prints a specified Occurrence from the server - * @param client The Grafeas client used to perform the API requests. - * @param occurrenceName the name of the Occurrence to delete - * format: "projects/[PROJECT_ID]/occurrences/[OCCURRENCE_ID]" - * @return the requested Occurrence object - */ - public static Occurrence getOccurrence(GrafeasV1Beta1Client client, String occurrenceName) { - Occurrence occ = client.getOccurrence(occurrenceName); - System.out.println(occ); - return occ; - } - // [END get_occurrence] - - // [START get_note] - /** - * Retrieves and prints a specified Note from the server - * @param client The Grafeas client used to perform the API requests. - * @param noteId the Note's unique identifier - * @param projectId the GCP project the Note belongs to - * @return the requested Note object - */ - public static Note getNote(GrafeasV1Beta1Client client, String noteId, String projectId) { - final NoteName noteName = NoteName.of(projectId, noteId); - - Note n = client.getNote(noteName); - System.out.println(n); - return n; - } - // [END get_note] - - // [START discovery_info] - /** - * Retrieves and prints the Discovery Occurrence created for a specified image - * The Discovery Occurrence contains information about the initial scan on the image - * @param client The Grafeas client used to perform the API requests. - * @param imageUrl the Container Registry URL associated with the image - * example: "https://gcr.io/project/image@sha256:foo" - * @param projectId the GCP project the image belongs to - */ - public static void getDiscoveryInfo(GrafeasV1Beta1Client client, String imageUrl, - String projectId) { - String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + imageUrl + "\""; - final String projectName = ProjectName.format(projectId); - - for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { - System.out.println(o); - } - } - // [END discovery_info] - - // [START occurrences_for_note] - /** - * Retrieves all the Occurrences associated with a specified Note - * Here, all Occurrences are printed and counted - * @param client The Grafeas client used to perform the API requests. - * @param noteId the Note's unique identifier - * @param projectId the GCP project the Note belongs to - * @return number of Occurrences found - */ - public static int getOccurrencesForNote(GrafeasV1Beta1Client client, String noteId, - String projectId) { - final NoteName noteName = NoteName.of(projectId, noteId); - int i = 0; - - ListNoteOccurrencesRequest request = ListNoteOccurrencesRequest.newBuilder() - .setName(noteName.toString()) - .build(); - for (Occurrence o : client.listNoteOccurrences(request).iterateAll()) { - // Write custom code to process each Occurrence here - System.out.println(o.getName()); - i = i + 1; - } - return i; - } - // [END occurrences_for_note] - - - // [START occurrences_for_image] - /** - * Retrieves all the Occurrences associated with a specified image - * Here, all Occurrences are simply printed and counted - * @param client The Grafeas client used to perform the API requests. - * @param imageUrl the Container Registry URL associated with the image - * example: "https://gcr.io/project/image@sha256:foo" - * @param projectId the GCP project to search for Occurrences in - * @return number of Occurrences found - */ - public static int getOccurrencesForImage(GrafeasV1Beta1Client client, String imageUrl, - String projectId) { - final String filterStr = "resourceUrl=\"" + imageUrl + "\""; - final String projectName = ProjectName.format(projectId); - int i = 0; - - for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { - // Write custom code to process each Occurrence here - System.out.println(o.getName()); - i = i + 1; - } - return i; - } - // [END occurrences_for_image] - - // [START pubsub] - /** - * Handle incoming Occurrences using a Cloud Pub/Sub subscription - * @param subId the user-specified identifier for the Pub/Sub subscription - * @param timeout the amount of time to listen for Pub/Sub messages (in seconds) - * @param projectId the GCP project the Pub/Sub subscription belongs to - * @return number of Occurrence Pub/Sub messages received before exiting - * @throws InterruptedException on errors with the subscription client - */ - public static int pubSub(String subId, int timeout, String projectId) - throws InterruptedException { - Subscriber subscriber = null; - MessageReceiverExample receiver = new MessageReceiverExample(); - - try { - // Subscribe to the requested Pub/Sub channel - ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId); - subscriber = Subscriber.newBuilder(subName, receiver).build(); - subscriber.startAsync().awaitRunning(); - // Listen to messages for 'timeout' seconds - for (int i = 0; i < timeout; i++) { - sleep(1000); - } - } finally { - // Stop listening to the channel - if (subscriber != null) { - subscriber.stopAsync(); - } - } - // Print and return the number of Pub/Sub messages received - System.out.println(receiver.messageCount); - return receiver.messageCount; - } - - - /** - * Custom class to handle incoming Pub/Sub messages - * In this case, the class will simply log and count each message as it comes in - */ - static class MessageReceiverExample implements MessageReceiver { - public int messageCount = 0; - - @Override - public synchronized void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) { - // Every time a Pub/Sub message comes in, print it and count it - System.out.println("Message " + messageCount + ": " + message.getData().toStringUtf8()); - messageCount += 1; - // Acknowledge the message - consumer.ack(); - } - } - - /** - * Creates and returns a Pub/Sub subscription object listening to the Occurrence topic - * @param subId the identifier you want to associate with the subscription - * @param projectId the GCP project to create the subscription under - * @throws IOException thrown on errors with the subscription client - * @throws StatusRuntimeException if subscription already exists - * - */ - public static Subscription createOccurrenceSubscription(String subId, String projectId) - throws IOException, StatusRuntimeException { - // This topic id will automatically receive messages when Occurrences are added or modified - String topicId = "container-analysis-occurrences-v1beta1"; - SubscriptionAdminClient client = SubscriptionAdminClient.create(); - PushConfig config = PushConfig.getDefaultInstance(); - ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId); - ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId); - Subscription sub = client.createSubscription(subName, topicName, config, 0); - return sub; - } - // [END pubsub] -} diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java new file mode 100644 index 00000000000..bd80e4b94ec --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_pubsub] +import com.google.cloud.pubsub.v1.AckReplyConsumer; +import com.google.cloud.pubsub.v1.MessageReceiver; +import com.google.cloud.pubsub.v1.Subscriber; +import com.google.cloud.pubsub.v1.SubscriptionAdminClient; +import com.google.pubsub.v1.ProjectSubscriptionName; +import com.google.pubsub.v1.ProjectTopicName; +import com.google.pubsub.v1.PubsubMessage; +import com.google.pubsub.v1.PushConfig; +import com.google.pubsub.v1.Subscription; +import io.grpc.StatusRuntimeException; +import java.io.IOException; +import java.lang.InterruptedException; +import java.util.concurrent.TimeUnit; + +public class Subscriptions { + // Handle incoming Occurrences using a Cloud Pub/Sub subscription + public static int pubSub(String subId, long timeoutSeconds, String projectId) + throws InterruptedException { + // String subId = "my-occurrence-subscription"; + // long timeoutSeconds = 20; + // String projectId = "my-project-id"; + Subscriber subscriber = null; + MessageReceiverExample receiver = new MessageReceiverExample(); + + try { + // Subscribe to the requested Pub/Sub channel + ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId); + subscriber = Subscriber.newBuilder(subName, receiver).build(); + subscriber.startAsync().awaitRunning(); + // Sleep to listen for messages + TimeUnit.SECONDS.sleep(timeoutSeconds); + } finally { + // Stop listening to the channel + if (subscriber != null) { + subscriber.stopAsync(); + } + } + // Print and return the number of Pub/Sub messages received + System.out.println(receiver.messageCount); + return receiver.messageCount; + } + + // Custom class to handle incoming Pub/Sub messages + // In this case, the class will simply log and count each message as it comes in + static class MessageReceiverExample implements MessageReceiver { + public int messageCount = 0; + + @Override + public synchronized void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) { + // Every time a Pub/Sub message comes in, print it and count it + System.out.println("Message " + messageCount + ": " + message.getData().toStringUtf8()); + messageCount += 1; + // Acknowledge the message + consumer.ack(); + } + } + + // Creates and returns a Pub/Sub subscription object listening to the Occurrence topic + public static Subscription createOccurrenceSubscription(String subId, String projectId) + throws IOException, StatusRuntimeException, InterruptedException { + // This topic id will automatically receive messages when Occurrences are added or modified + String topicId = "container-analysis-occurrences-v1beta1"; + ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId); + ProjectSubscriptionName subName = ProjectSubscriptionName.of(projectId, subId); + + SubscriptionAdminClient client = SubscriptionAdminClient.create(); + PushConfig config = PushConfig.getDefaultInstance(); + Subscription sub = client.createSubscription(subName, topicName, config, 0); + return sub; + } +} +// [END containeranalysis_pubsub] diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/VulnerabilityOccurrencesForImage.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/VulnerabilityOccurrencesForImage.java new file mode 100644 index 00000000000..2ccf2f465c6 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/VulnerabilityOccurrencesForImage.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 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.containeranalysis; + +// [START containeranalysis_vulnerability_occurrences_for_image] +import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; +import com.google.containeranalysis.v1beta1.ProjectName; +import io.grafeas.v1beta1.Occurrence; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +public class VulnerabilityOccurrencesForImage { + // Retrieve a list of vulnerability occurrences assoviated with a resource + public static List findVulnerabilityOccurrencesForImage(String resourceUrl, + String projectId) throws IOException { + // String resourceUrl = "https://gcr.io/project/image@sha256:123"; + // String projectId = "my-project-id"; + final String projectName = ProjectName.format(projectId); + String filterStr = String.format("kind=\"VULNERABILITY\" AND resourceUrl=\"%s\"", resourceUrl); + + // Initialize client that will be used to send requests. After completing all of your requests, + // call the "close" method on the client to safely clean up any remaining background resources. + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + LinkedList vulnerabilitylist = new LinkedList(); + for (Occurrence o : client.listOccurrences(projectName, filterStr).iterateAll()) { + vulnerabilitylist.add(o); + } + return vulnerabilitylist; + } +} +// [END containeranalysis_vulnerability_occurrences_for_image] diff --git a/container-registry/container-analysis/src/test/java/com/example/containeranalysis/SamplesTest.java b/container-registry/container-analysis/src/test/java/com/example/containeranalysis/SamplesTest.java index 717bacbba6d..6f21dfa23e0 100644 --- a/container-registry/container-analysis/src/test/java/com/example/containeranalysis/SamplesTest.java +++ b/container-registry/container-analysis/src/test/java/com/example/containeranalysis/SamplesTest.java @@ -17,22 +17,31 @@ package com.example.containeranalysis; import static java.lang.Thread.sleep; -import static junit.framework.Assert.fail; import static junit.framework.TestCase.assertEquals; import com.google.api.gax.rpc.NotFoundException; import com.google.cloud.devtools.containeranalysis.v1beta1.GrafeasV1Beta1Client; import com.google.cloud.pubsub.v1.Subscriber; import com.google.cloud.pubsub.v1.SubscriptionAdminClient; +import com.google.containeranalysis.v1beta1.NoteName; +import com.google.containeranalysis.v1beta1.ProjectName; import com.google.pubsub.v1.ProjectSubscriptionName; import io.grafeas.v1beta1.Note; import io.grafeas.v1beta1.Occurrence; +import io.grafeas.v1beta1.Resource; +import io.grafeas.v1beta1.discovery.Discovered; +import io.grafeas.v1beta1.discovery.Discovered.AnalysisStatus; +import io.grafeas.v1beta1.discovery.Discovery; import io.grafeas.v1beta1.vulnerability.Details; +import io.grafeas.v1beta1.vulnerability.Severity; import io.grafeas.v1beta1.vulnerability.Vulnerability; import io.grpc.StatusRuntimeException; import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeoutException; import org.junit.After; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; @@ -50,7 +59,6 @@ public class SamplesTest { private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); private static final String subId = "CA-Occurrences-" + (new Date()).getTime(); - private static GrafeasV1Beta1Client client; private String noteId; private String imageUrl; private Note noteObj; @@ -60,15 +68,11 @@ public class SamplesTest { @Rule public TestName name = new TestName(); - @BeforeClass - public static void setUpClass() throws Exception { - client = GrafeasV1Beta1Client.create(); - } + @AfterClass public static void tearDownClass() { try { - client.shutdownNow(); SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create(); ProjectSubscriptionName subName = ProjectSubscriptionName.of(PROJECT_ID, subId); subscriptionAdminClient.deleteSubscription(subName); @@ -85,13 +89,13 @@ public void setUp() throws Exception { System.out.println(name.getMethodName()); noteId = "note-" + (new Date()).getTime() + name.getMethodName(); imageUrl = "www." + (new Date()).getTime() + name.getMethodName() + ".com"; - noteObj = Samples.createNote(client, noteId, PROJECT_ID); + noteObj = CreateNote.createNote(noteId, PROJECT_ID); } @After public void tearDown() { try { - Samples.deleteNote(client, noteId, PROJECT_ID); + DeleteNote.deleteNote(noteId, PROJECT_ID); } catch (Exception e) { // these exceptions aren't relevant to the tests System.out.println("TearDown Error: " + e.toString()); @@ -101,90 +105,62 @@ public void tearDown() { @Test public void testCreateNote() throws Exception { // note should have been created as part of set up. verify that it succeeded - Note n = Samples.getNote(client, noteId, PROJECT_ID); + Note n = GetNote.getNote(noteId, PROJECT_ID); assertEquals(n.getName(), noteObj.getName()); } @Test public void testDeleteNote() throws Exception { - Samples.deleteNote(client, noteId, PROJECT_ID); + DeleteNote.deleteNote(noteId, PROJECT_ID); try { - Samples.getNote(client, noteId, PROJECT_ID); + GetNote.getNote(noteId, PROJECT_ID); // above should throw, because note was deleted - fail("note not deleted"); + Assert.fail("note not deleted"); } catch (NotFoundException e) { // test passes } } - @Test - public void testUpdateNote() throws Exception { - String descriptionText = "updated"; - - Note.Builder builder = Note.newBuilder(noteObj); - builder.setShortDescription(descriptionText); - Note returned = Samples.updateNote(client, builder.build(), noteId, PROJECT_ID); - assertEquals(descriptionText, returned.getShortDescription()); - - Note updated = Samples.getNote(client, noteId, PROJECT_ID); - assertEquals(descriptionText, updated.getShortDescription()); - } - @Test public void testCreateOccurrence() throws Exception { - Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); - Occurrence retrieved = Samples.getOccurrence(client, o.getName()); + Occurrence o = CreateOccurrence.createOccurrence(imageUrl, noteId, PROJECT_ID, PROJECT_ID); + String[] nameArr = o.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + Occurrence retrieved = GetOccurrence.getOccurrence(occId, PROJECT_ID); assertEquals(o.getName(), retrieved.getName()); // clean up - Samples.deleteOccurrence(client, o.getName()); + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); } @Test public void testDeleteOccurrence() throws Exception { - Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); + Occurrence o = CreateOccurrence.createOccurrence(imageUrl, noteId, PROJECT_ID, PROJECT_ID); String occName = o.getName(); + String[] nameArr = occName.split("/"); + String occId = nameArr[nameArr.length - 1]; - Samples.deleteOccurrence(client, occName); + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); try { - Samples.getOccurrence(client, occName); + GetOccurrence.getOccurrence(occId, PROJECT_ID); // getOccurrence should fail, because occurrence was deleted - fail("failed to delete occurrence"); + Assert.fail("failed to delete occurrence"); } catch (NotFoundException e) { // test passes } } - @Test - public void testUpdateOccurrence() throws Exception { - String typeId = "newType"; - - Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); - - Occurrence.Builder b = Occurrence.newBuilder(o); - Details.Builder d = Details.newBuilder(); - d.setType(typeId); - b.setVulnerability(d); - - Occurrence returned = Samples.updateOccurrence(client, o.getName(), b.build()); - assertEquals(typeId, returned.getVulnerability().getType()); - Occurrence got = Samples.getOccurrence(client, o.getName()); - assertEquals(typeId, got.getVulnerability().getType()); - - // clean up - Samples.deleteOccurrence(client, o.getName()); - } - @Test public void testOccurrencesForImage() throws Exception { int newCount; int tries = 0; - int origCount = Samples.getOccurrencesForImage(client, imageUrl, PROJECT_ID); - final Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); + int origCount = OccurrencesForImage.getOccurrencesForImage(imageUrl, PROJECT_ID); + final Occurrence o = CreateOccurrence.createOccurrence( + imageUrl, noteId, PROJECT_ID, PROJECT_ID); do { - newCount = Samples.getOccurrencesForImage(client, imageUrl, PROJECT_ID); + newCount = OccurrencesForImage.getOccurrencesForImage(imageUrl, PROJECT_ID); sleep(SLEEP_TIME); tries += 1; } while (newCount != 1 && tries < TRY_LIMIT); @@ -192,17 +168,20 @@ public void testOccurrencesForImage() throws Exception { assertEquals(0, origCount); // clean up - Samples.deleteOccurrence(client, o.getName()); + String[] nameArr = o.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); } @Test public void testOccurrencesForNote() throws Exception { int newCount; int tries = 0; - int origCount = Samples.getOccurrencesForNote(client, noteId, PROJECT_ID); - final Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); + int origCount = OccurrencesForNote.getOccurrencesForNote(noteId, PROJECT_ID); + final Occurrence o = CreateOccurrence.createOccurrence( + imageUrl, noteId, PROJECT_ID, PROJECT_ID); do { - newCount = Samples.getOccurrencesForNote(client, noteId, PROJECT_ID); + newCount = OccurrencesForNote.getOccurrencesForNote(noteId, PROJECT_ID); sleep(SLEEP_TIME); tries += 1; } while (newCount != 1 && tries < TRY_LIMIT); @@ -210,7 +189,9 @@ public void testOccurrencesForNote() throws Exception { assertEquals(1, newCount); // clean up - Samples.deleteOccurrence(client, o.getName()); + String[] nameArr = o.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); } @Test @@ -219,12 +200,12 @@ public void testPubSub() throws Exception { int tries; ProjectSubscriptionName subName = ProjectSubscriptionName.of(PROJECT_ID, subId); try { - Samples.createOccurrenceSubscription(subId, PROJECT_ID); + Subscriptions.createOccurrenceSubscription(subId, PROJECT_ID); } catch (StatusRuntimeException e) { System.out.println("subscription " + subId + " already exists"); } Subscriber subscriber = null; - Samples.MessageReceiverExample receiver = new Samples.MessageReceiverExample(); + Subscriptions.MessageReceiverExample receiver = new Subscriptions.MessageReceiverExample(); subscriber = Subscriber.newBuilder(subName, receiver).build(); subscriber.startAsync().awaitRunning(); @@ -235,7 +216,7 @@ public void testPubSub() throws Exception { // now, we can test adding 3 more occurrences int endVal = startVal + 3; for (int i = startVal; i <= endVal; i++) { - Occurrence o = Samples.createOccurrence(client, imageUrl, noteId, PROJECT_ID, PROJECT_ID); + Occurrence o = CreateOccurrence.createOccurrence(imageUrl, noteId, PROJECT_ID, PROJECT_ID); System.out.println("CREATED: " + o.getName()); tries = 0; do { @@ -245,10 +226,136 @@ public void testPubSub() throws Exception { } while (newCount != i && tries < TRY_LIMIT); System.out.println(receiver.messageCount + " : " + i); assertEquals(i, receiver.messageCount); - Samples.deleteOccurrence(client, o.getName()); + String[] nameArr = o.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); } if (subscriber != null) { subscriber.stopAsync(); } } + + @Test + public void testPollDiscoveryOccurrenceFinished() throws Exception { + try { + // expect fail on first try + PollDiscoveryOccurrenceFinished.pollDiscoveryOccurrenceFinished(imageUrl, PROJECT_ID, 5); + Assert.fail("found unexpected discovery occurrence"); + } catch (TimeoutException e) { + // test passes + } + // create discovery note + String discNoteId = "discovery-note-" + (new Date()).getTime(); + NoteName noteName = NoteName.of(PROJECT_ID, discNoteId); + Note.Builder noteBuilder = Note.newBuilder(); + Discovery.Builder discoveryBuilder = Discovery.newBuilder(); + noteBuilder.setDiscovery(discoveryBuilder); + Note newNote = noteBuilder.build(); + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + client.createNote(ProjectName.format(PROJECT_ID), discNoteId, newNote); + + // create discovery occurrence + Occurrence.Builder occBuilder = Occurrence.newBuilder(); + occBuilder.setNoteName(noteName.toString()); + Discovered.Builder discoveredBuilder = Discovered.newBuilder(); + discoveredBuilder.setAnalysisStatus(AnalysisStatus.FINISHED_SUCCESS); + io.grafeas.v1beta1.discovery.Details.Builder detailsBuilder = + io.grafeas.v1beta1.discovery.Details.newBuilder(); + detailsBuilder.setDiscovered(discoveredBuilder); + occBuilder.setDiscovered(detailsBuilder); + Resource.Builder resourceBuilder = Resource.newBuilder(); + resourceBuilder.setUri(imageUrl); + occBuilder.setResource(resourceBuilder); + Occurrence newOcc = occBuilder.build(); + Occurrence result = client.createOccurrence(ProjectName.format(PROJECT_ID), newOcc); + + // poll again + Occurrence found = PollDiscoveryOccurrenceFinished.pollDiscoveryOccurrenceFinished( + imageUrl, PROJECT_ID, 5); + AnalysisStatus foundStatus = found.getDiscovered().getDiscovered().getAnalysisStatus(); + assertEquals(foundStatus, AnalysisStatus.FINISHED_SUCCESS); + + // clean up + String[] nameArr = found.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); + DeleteNote.deleteNote(discNoteId, PROJECT_ID); + } + + @Test + public void testFindVulnerabilitiesForImage() throws Exception { + List result = VulnerabilityOccurrencesForImage.findVulnerabilityOccurrencesForImage( + imageUrl, PROJECT_ID); + assertEquals(result.size(), 0); + Occurrence o = CreateOccurrence.createOccurrence(imageUrl, noteId, PROJECT_ID, PROJECT_ID); + int tries = 0; + do { + result = VulnerabilityOccurrencesForImage.findVulnerabilityOccurrencesForImage( + imageUrl, PROJECT_ID); + sleep(SLEEP_TIME); + tries += 1; + } while (result.size() != 1 && tries < TRY_LIMIT); + assertEquals(result.size(), 1); + + // clean up + String[] nameArr = o.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); + } + + @Test + public void testFindHighSeverityVulnerabilitiesForImage() throws Exception { + // check before creation + List result = HighVulnerabilitiesForImage.findHighSeverityVulnerabilitiesForImage( + imageUrl, PROJECT_ID); + assertEquals(0, result.size()); + + // create low severity occurrence + Occurrence low; + low = CreateOccurrence.createOccurrence(imageUrl, noteId, PROJECT_ID, PROJECT_ID); + result = HighVulnerabilitiesForImage.findHighSeverityVulnerabilitiesForImage( + imageUrl, PROJECT_ID); + assertEquals(0, result.size()); + + // create high severity note + String vulnNoteId = "discovery-note-" + (new Date()).getTime(); + Note.Builder noteBuilder = Note.newBuilder(); + Vulnerability.Builder vulnBuilder = Vulnerability.newBuilder(); + vulnBuilder.setSeverity(Severity.CRITICAL); + noteBuilder.setVulnerability(vulnBuilder); + Note newNote = noteBuilder.build(); + GrafeasV1Beta1Client client = GrafeasV1Beta1Client.create(); + client.createNote(ProjectName.format(PROJECT_ID), vulnNoteId, newNote); + + // create high severity occurrence + Occurrence.Builder occBuilder = Occurrence.newBuilder(); + NoteName noteName = NoteName.of(PROJECT_ID, vulnNoteId); + occBuilder.setNoteName(noteName.toString()); + Details.Builder detailsBuilder = Details.newBuilder(); + occBuilder.setVulnerability(detailsBuilder); + Resource.Builder resourceBuilder = Resource.newBuilder(); + resourceBuilder.setUri(imageUrl); + occBuilder.setResource(resourceBuilder); + Occurrence critical = occBuilder.build(); + critical = client.createOccurrence(ProjectName.format(PROJECT_ID), critical); + + // check again + int tries = 0; + do { + result = HighVulnerabilitiesForImage.findHighSeverityVulnerabilitiesForImage( + imageUrl, PROJECT_ID); + sleep(SLEEP_TIME); + tries += 1; + } while (result.size() != 1 && tries < TRY_LIMIT); + assertEquals(1, result.size()); + + // clean up + String[] lowNameArr = low.getName().split("/"); + String lowId = lowNameArr[lowNameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(lowId, PROJECT_ID); + String[] nameArr = critical.getName().split("/"); + String occId = nameArr[nameArr.length - 1]; + DeleteOccurrence.deleteOccurrence(occId, PROJECT_ID); + DeleteNote.deleteNote(vulnNoteId, PROJECT_ID); + } } diff --git a/datacatalog/cloud-client/README.md b/datacatalog/cloud-client/README.md new file mode 100644 index 00000000000..f4128e2c4b0 --- /dev/null +++ b/datacatalog/cloud-client/README.md @@ -0,0 +1,31 @@ +# Getting Started with Data Catalog and the Google Cloud Client libraries + + +Open in Cloud Shell + +[Data Catalog][datacatalog] is a fully managed and scalable metadata management service that empowers organizations +to quickly discover, manage, and understand all their data in Google Cloud. +This sample Java application demonstrates how to access the Data Catalog API using +the [Google Cloud Client Library for Java][google-cloud-java]. + +[datacatalog]: https://cloud.google.com/data-catalog/ +[google-cloud-java]: https://github.com/GoogleCloudPlatform/google-cloud-java + +## Quickstart + +#### Setup +- Install [Maven](http://maven.apache.org/). +- [Enable](https://console.cloud.google.com/apis/api/datacatalog.googleapis.com/overview) Data Catalog API. +- Set up [authentication](https://cloud.google.com/docs/authentication/getting-started). + +#### Build +- Build your project with: +``` + mvn clean package -DskipTests +``` + +#### Testing +Run the test with Maven. +``` + mvn verify +``` diff --git a/datacatalog/cloud-client/build.gradle b/datacatalog/cloud-client/build.gradle new file mode 100644 index 00000000000..cb6066b14b0 --- /dev/null +++ b/datacatalog/cloud-client/build.gradle @@ -0,0 +1,41 @@ +// Copyright 2019 Google Inc. +// +// 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. + +apply plugin: 'java' + +repositories { + mavenCentral() +} + +dependencies { + compile group: 'com.google.cloud', name: 'google-cloud-datacatalog', version:'0.4.0-alpha' + + testCompile group: 'com.google.truth', name: 'truth', version:'0.42' + testCompile group: 'junit', name: 'junit', version:'4.13-beta-2' +} + +test { + useJUnit() + testLogging.showStandardStreams = true + beforeTest { descriptor -> + logger.lifecycle("test: " + descriptor + " Running") + } + + onOutput { descriptor, event -> + logger.lifecycle("test: " + descriptor + ": " + event.message ) + } + afterTest { descriptor, result -> + logger.lifecycle("test: " + descriptor + ": " + result ) + } +} diff --git a/datacatalog/cloud-client/pom.xml b/datacatalog/cloud-client/pom.xml new file mode 100644 index 00000000000..9ccd5c45756 --- /dev/null +++ b/datacatalog/cloud-client/pom.xml @@ -0,0 +1,59 @@ + + + + 4.0.0 + com.example.datacatalog + datacatalog-google-cloud-samples + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + 1.8 + 1.8 + + + + + com.google.cloud + google-cloud-datacatalog + 0.4.0-alpha + + + + + junit + junit + 4.13-beta-2 + test + + + com.google.truth + truth + 0.42 + test + + + diff --git a/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java new file mode 100644 index 00000000000..4c4ee950d06 --- /dev/null +++ b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.datacatalog; + +// [START datacatalog_bigquery_lookup_dataset] +import com.google.cloud.datacatalog.Entry; +import com.google.cloud.datacatalog.LookupEntryRequest; +import com.google.cloud.datacatalog.v1beta1.DataCatalogClient; + +public class LookupEntryBigQueryDataset { + + /** + * Lookup the Data Catalog entry referring to a BigQuery Dataset + * + * @param projectId The project ID to which the Dataset belongs, e.g. 'my-project' + * @param datasetId The dataset ID to which the Catalog Entry refers, e.g. 'my_dataset' + */ + public static void lookupEntry(String projectId, String datasetId) { + // String projectId = "my-project" + // String datasetId = "my_dataset" + + // Get an entry by the resource name from the source Google Cloud Platform service. + String linkedResource = + String.format("//bigquery.googleapis.com/projects/%s/datasets/%s", projectId, datasetId); + LookupEntryRequest request = + LookupEntryRequest.newBuilder().setLinkedResource(linkedResource).build(); + + // Alternatively, lookup by the SQL name of the entry would have the same result: + // String sqlResource = String.format("bigquery.dataset.`%s`.`%s`", projectId, datasetId); + // LookupEntryRequest request = + // LookupEntryRequest.newBuilder().setSqlResource(sqlResource).build(); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. + try (DataCatalogClient dataCatalogClient = DataCatalogClient.create()) { + Entry entry = dataCatalogClient.lookupEntry(request); + System.out.printf("Entry name: %s\n", entry.getName()); + } catch (Exception e) { + System.out.print("Error during lookupEntryBigQueryDataset:\n" + e.toString()); + } + } +} +// [END datacatalog_bigquery_lookup_dataset] diff --git a/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryTable.java b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryTable.java new file mode 100644 index 00000000000..bae8e35c361 --- /dev/null +++ b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryTable.java @@ -0,0 +1,61 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.datacatalog; + +import com.google.cloud.datacatalog.Entry; +import com.google.cloud.datacatalog.LookupEntryRequest; +import com.google.cloud.datacatalog.v1beta1.DataCatalogClient; + +public class LookupEntryBigQueryTable { + + /** + * Lookup the Data Catalog entry referring to a BigQuery Table + * + * @param projectId The project ID to which the Dataset belongs, e.g. 'my-project' + * @param datasetId The dataset ID to which the Table belongs, e.g. 'my_dataset' + * @param tableId The table ID to which the Catalog Entry refers, e.g. 'my_table' + */ + public static void lookupEntry(String projectId, String datasetId, String tableId) { + // String projectId = "my-project" + // String datasetId = "my_dataset" + // String tableId = "my_table" + + // Get an entry by the resource name from the source Google Cloud Platform service. + String linkedResource = + String.format( + "//bigquery.googleapis.com/projects/%s/datasets/%s/tables/%s", + projectId, datasetId, tableId); + LookupEntryRequest request = + LookupEntryRequest.newBuilder().setLinkedResource(linkedResource).build(); + + // Alternatively, lookup by the SQL name of the entry would have the same result: + // String sqlResource = String.format("bigquery.table.`%s`.`%s`.`%s`", projectId, datasetId, + // tableId); + // LookupEntryRequest request = + // LookupEntryRequest.newBuilder().setSqlResource(sqlResource).build(); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. + try (DataCatalogClient dataCatalogClient = DataCatalogClient.create()) { + Entry entry = dataCatalogClient.lookupEntry(request); + System.out.printf("Entry name: %s\n", entry.getName()); + } catch (Exception e) { + System.out.print("Error during lookupEntryBigQueryTable:\n" + e.toString()); + } + } +} diff --git a/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryPubSubTopic.java b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryPubSubTopic.java new file mode 100644 index 00000000000..53195fffa9d --- /dev/null +++ b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryPubSubTopic.java @@ -0,0 +1,56 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.datacatalog; + +import com.google.cloud.datacatalog.Entry; +import com.google.cloud.datacatalog.LookupEntryRequest; +import com.google.cloud.datacatalog.v1beta1.DataCatalogClient; + +public class LookupEntryPubSubTopic { + + /** + * Lookup the Data Catalog entry referring to a BigQuery Dataset + * + * @param projectId The project ID to which the Dataset belongs, e.g. 'my-project' + * @param topicId The topic ID to which the Catalog Entry refers, e.g. 'my-topic' + */ + public static void lookupEntry(String projectId, String topicId) { + // String projectId = "my-project" + // String topicId = "my-topic" + + // Get an entry by the resource name from the source Google Cloud Platform service. + String linkedResource = + String.format("//pubsub.googleapis.com/projects/%s/topics/%s", projectId, topicId); + LookupEntryRequest request = + LookupEntryRequest.newBuilder().setLinkedResource(linkedResource).build(); + + // Alternatively, lookup by the SQL name of the entry would have the same result: + // String sqlResource = String.format("pubsub.topic.`%s`.`%s`", projectId, topicId); + // LookupEntryRequest request = + // LookupEntryRequest.newBuilder().setSqlResource(sqlResource).build(); + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. + try (DataCatalogClient dataCatalogClient = DataCatalogClient.create()) { + Entry entry = dataCatalogClient.lookupEntry(request); + System.out.printf("Entry name: %s\n", entry.getName()); + } catch (Exception e) { + System.out.print("Error during lookupEntryPubSubTopic:\n" + e.toString()); + } + } +} diff --git a/datacatalog/cloud-client/src/test/java/com/example/datacatalog/LookupEntryTests.java b/datacatalog/cloud-client/src/test/java/com/example/datacatalog/LookupEntryTests.java new file mode 100644 index 00000000000..bf254fec42e --- /dev/null +++ b/datacatalog/cloud-client/src/test/java/com/example/datacatalog/LookupEntryTests.java @@ -0,0 +1,81 @@ +/* + * Copyright 2019 Google Inc. + * + * 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.datacatalog; + +import static com.google.common.truth.Truth.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class LookupEntryTests { + + private static final String BIGQUERY_PROJECT = "bigquery-public-data"; + private static final String BIGQUERY_DATASET = "new_york_taxi_trips"; + private static final String BIGQUERY_TABLE = "taxi_zone_geom"; + + private static final String PUBSUB_PROJECT = "pubsub-public-data"; + private static final String PUBSUB_TOPIC = "taxirides-realtime"; + + private ByteArrayOutputStream bout; + + @Before + public void setUp() { + bout = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(bout); + System.setOut(out); + } + + @After + public void tearDown() throws IOException { + bout.close(); + System.setOut(null); + } + + @Test + public void testLookupEntryBigQueryDataset() { + LookupEntryBigQueryDataset.lookupEntry(BIGQUERY_PROJECT, BIGQUERY_DATASET); + String got = bout.toString(); + assertThat(got) + .containsMatch( + "projects/" + BIGQUERY_PROJECT + "/locations/.+?/entryGroups/@bigquery/entries/.+?$"); + } + + @Test + public void testLookupEntryBigQueryTable() { + LookupEntryBigQueryTable.lookupEntry(BIGQUERY_PROJECT, BIGQUERY_DATASET, BIGQUERY_TABLE); + String got = bout.toString(); + assertThat(got) + .containsMatch( + "projects/" + BIGQUERY_PROJECT + "/locations/.+?/entryGroups/@bigquery/entries/.+?$"); + } + + @Test + public void testLookupPubSubTopic() { + LookupEntryPubSubTopic.lookupEntry(PUBSUB_PROJECT, PUBSUB_TOPIC); + String got = bout.toString(); + assertThat(got) + .containsMatch( + "projects/" + PUBSUB_PROJECT + "/locations/.+?/entryGroups/@pubsub/entries/.+?$"); + } +} diff --git a/dataflow/spanner-io/pom.xml b/dataflow/spanner-io/pom.xml index abc725e31a3..4b82d7490de 100644 --- a/dataflow/spanner-io/pom.xml +++ b/dataflow/spanner-io/pom.xml @@ -30,7 +30,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 @@ -38,7 +38,7 @@ 1.8 1.8 1.8 - 2.3.0 + 2.5.0 @@ -51,7 +51,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.19.1 + 3.0.0-M3 default-instance diff --git a/dataflow/spanner-io/src/main/java/com/example/dataflow/SpannerReadAll.java b/dataflow/spanner-io/src/main/java/com/example/dataflow/SpannerReadAll.java index b0eb417ced5..7460f07af4a 100644 --- a/dataflow/spanner-io/src/main/java/com/example/dataflow/SpannerReadAll.java +++ b/dataflow/spanner-io/src/main/java/com/example/dataflow/SpannerReadAll.java @@ -69,6 +69,7 @@ public static void main(String[] args) { // [START spanner_dataflow_readall] PCollection allRecords = p.apply(SpannerIO.read() .withSpannerConfig(spannerConfig) + .withBatching(false) .withQuery("SELECT t.table_name FROM information_schema.tables AS t WHERE t" + ".table_catalog = '' AND t.table_schema = ''")).apply( MapElements.into(TypeDescriptor.of(ReadOperation.class)) diff --git a/dataflow/transforms/pom.xml b/dataflow/transforms/pom.xml index 9f96109ce69..b99f573c751 100644 --- a/dataflow/transforms/pom.xml +++ b/dataflow/transforms/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/datalabeling/beta/cloud-client/pom.xml b/datalabeling/beta/cloud-client/pom.xml index 0059bb5579a..8bcfe52b03c 100644 --- a/datalabeling/beta/cloud-client/pom.xml +++ b/datalabeling/beta/cloud-client/pom.xml @@ -23,7 +23,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/datastore/cloud-client/pom.xml b/datastore/cloud-client/pom.xml index 737a891977a..39f36ff6387 100644 --- a/datastore/cloud-client/pom.xml +++ b/datastore/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/datastore/pom.xml b/datastore/pom.xml index 43a335439df..379fb7f3a32 100644 --- a/datastore/pom.xml +++ b/datastore/pom.xml @@ -32,7 +32,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/datastore/src/test/java/com/google/datastore/snippets/ConceptsTest.java b/datastore/src/test/java/com/google/datastore/snippets/ConceptsTest.java index abb1ba5e860..ce6b59d8fd2 100644 --- a/datastore/src/test/java/com/google/datastore/snippets/ConceptsTest.java +++ b/datastore/src/test/java/com/google/datastore/snippets/ConceptsTest.java @@ -233,6 +233,9 @@ public void testArrayValue() { @Test public void testBasicEntity() { // [START datastore_basic_entity] + Key taskKey = datastore.newKeyFactory() + .setKind("Task") + .newKey("sampleTask"); Entity task = Entity.newBuilder(taskKey) .set("category", "Personal") .set("done", false) diff --git a/dialogflow/cloud-client/pom.xml b/dialogflow/cloud-client/pom.xml index 39088f5d6fb..bd1f4e8412c 100644 --- a/dialogflow/cloud-client/pom.xml +++ b/dialogflow/cloud-client/pom.xml @@ -23,7 +23,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 @@ -40,7 +40,7 @@ com.google.cloud google-cloud-dialogflow - 0.88.0-alpha + 0.91.0-alpha @@ -57,1394 +57,4 @@ test
- - - - - ContextManagement - - - ContextManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.ContextManagement - false - - - - - - - - - ContextManagementList - - - ContextManagementList - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.ContextManagement - - list - --sessionId - ${sessionId} - --projectId - ${projectId} - - false - - - - - - - - - ContextManagementCreate - - - ContextManagementCreate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.ContextManagement - - create - --sessionId - ${sessionId} - --projectId - ${projectId} - --contextId - ${contextId} - - false - - - - - - - - - ContextManagementDelete - - - ContextManagementDelete - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.ContextManagement - - delete - --sessionId - ${sessionId} - --projectId - ${projectId} - --contextId - ${contextId} - - false - - - - - - - - - DetectIntentAudio - - - DetectIntentAudio - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - false - - - - - - - - - DetectIntentAudioBookARoom - - - DetectIntentAudioBookARoom - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/book_a_room.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentAudioMountainView - - - DetectIntentAudioMountainView - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/mountain_view.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentAudioToday - - - DetectIntentAudioToday - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/today.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentAudio230PM - - - DetectIntentAudio230PM - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/230pm.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentAudioHalfAnHour - - - DetectIntentAudioHalfAnHour - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/half_an_hour.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentAudioTwoPeople - - - DetectIntentAudioTwoPeople - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentAudio - - --projectId - ${projectId} - --audioFilePath - resources/two_people.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentStreamBookARoom - - - DetectIntentStreamBookARoom - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentStream - - --projectId - ${projectId} - --audioFilePath - resources/book_a_room.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentStream - - - DetectIntentStream - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentStream - false - - - - - - - - - DetectIntentStreamMountainView - - - DetectIntentStreamMountainView - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentStream - - --projectId - ${projectId} - --audioFilePath - resources/mountain_view.wav - --sessionId - ${sessionId} - - false - - - - - - - - - DetectIntentTexts - - - DetectIntentTexts - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentTexts - false - - - - - - - - - DetectIntentText - - - DetectIntentText - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentTexts - - --projectId - ${projectId} - --sessionId - ${sessionId} - "hello" - "book a meeting room" - "Mountain View" - "tomorrow" - "10 am" - "2 hours" - "10 people" - "A" - "yes" - - false - - - - - - - - - DetectIntentWithTTSResponses - - - DetectIntentWithTTSResponses - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentWithTextToSpeechResponse - false - - - - - - - - - DetectIntentTTSResponse - - - DetectIntentTTSResponse - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentWithTextToSpeechResponse - - --projectId - ${projectId} - --sessionId - ${sessionId} - "hello" - "book a meeting room" - "Mountain View" - "tomorrow" - "10 am" - "2 hours" - "10 people" - "A" - "yes" - - false - - - - - - - - - DetectIntentSentimentAnalysis - - - DetectIntentSentimentAnalysis - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentWithSentimentAnalysis - false - - - - - - - - - DetectIntentKnowledge - - - DetectIntentKnowledge - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentKnowledge - false - - - - - - - - - - EntityManagement - - - EntityManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityManagement - false - - - - - - - - - DetectIntentWithModelSelection - - - DetectIntentWithModelSelection - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DetectIntentWithModelSelection - false - - - - - - - - - EntityManagementList - - - EntityManagementList - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityManagement - - list - --projectId - ${projectId} - --entityTypeId - e57238e2-e692-44ea-9216-6be1b2332e2a - - false - - - - - - - - - EntityManagementCreate - - - EntityManagementCreate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityManagement - - create - new_room - --projectId - ${projectId} - --entityTypeId - e57238e2-e692-44ea-9216-6be1b2332e2a - --synonyms - basement - cellar - - false - - - - - - - - - EntityManagementDelete - - - EntityManagementDelete - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityManagement - - delete - new_room - --projectId - ${projectId} - --entityTypeId - e57238e2-e692-44ea-9216-6be1b2332e2a - - false - - - - - - - - - EntityTypeManagement - - - EntityTypeManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityTypeManagement - false - - - - - - - - - EntityTypeManagementList - - - EntityTypeManagementList - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityTypeManagement - - list - --projectId - ${projectId} - - false - - - - - - - - - EntityTypeManagementCreate - - - EntityTypeManagementCreate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityTypeManagement - - create - employee - --projectId - ${projectId} - - false - - - - - - - - - EntityTypeManagementDelete - - - EntityTypeManagementDelete - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.EntityTypeManagement - - delete - - - - - false - - - - - - - - - IntentManagement - - - IntentManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.IntentManagement - false - - - - - - - - - IntentManagementList - - - IntentManagementList - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.IntentManagement - - list - --projectId - ${projectId} - - false - - - - - - - - - IntentManagementCreate - - - IntentManagementCreate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.IntentManagement - - create - "room.cancellation - yes" - --projectId - ${projectId} - --action - room.cancel - --trainingPhrasesParts - "cancel" - "cancellation" - --messageTexts - "Are you sure you want to cancel?" - "Cancelled." - - false - - - - - - - - - IntentManagementDelete - - - IntentManagementDelete - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.IntentManagement - - - - - - - false - - - - - - - - - KnowledgeBaseManagement - - - KnowledgeBaseManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.KnowledgeBaseManagement - false - - - - - - - - - DocumentManagement - - - DocumentManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.DocumentManagement - false - - - - - - - - - SessionEntityTypeManagement - - - SessionEntityTypeManagement - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.SessionEntityTypeManagement - false - - - - - - - - - SessionEntityTypeManagementList - - - SessionEntityTypeManagementList - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.SessionEntityTypeManagement - - list - --projectId - ${projectId} - --sessionId - ${sessionId} - - false - - - - - - - - - SessionEntityTypeManagementCreate - - - SessionEntityTypeManagementCreate - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.SessionEntityTypeManagement - - create - --projectId - ${projectId} - --sessionId - ${sessionId} - --entityTypeDisplayName - room - --entityValues - C - D - E - F - - false - - - - - - - - - SessionEntityTypeManagementDelete - - - SessionEntityTypeManagementDelete - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.6.0 - - - - java - - - - - com.example.dialogflow.SessionEntityTypeManagement - - delete - --projectId - ${projectId} - --sessionId - ${sessionId} - --entityTypeDisplayName - room - - false - - - - - - diff --git a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentStream.java b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentStream.java index b531fd180d3..94a7d4df8d8 100644 --- a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentStream.java +++ b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentStream.java @@ -16,10 +16,9 @@ package com.example.dialogflow; - +// [START dialogflow_detect_intent_streaming] // Imports the Google Cloud client library - -import com.google.api.gax.rpc.ApiStreamObserver; +import com.google.api.gax.rpc.BidiStream; import com.google.cloud.dialogflow.v2.AudioEncoding; import com.google.cloud.dialogflow.v2.InputAudioConfig; import com.google.cloud.dialogflow.v2.QueryInput; @@ -29,138 +28,77 @@ import com.google.cloud.dialogflow.v2.StreamingDetectIntentRequest; import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse; import com.google.protobuf.ByteString; - import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; +import java.io.IOException; /** * DialogFlow API Detect Intent sample with audio files processes as an audio stream. */ -public class DetectIntentStream { - // [START dialogflow_detect_intent_streaming] +class DetectIntentStream { - /** - * Returns the result of detect intent with streaming audio as input. - * - * Using the same `session_id` between requests allows continuation of the conversation. - * - * @param projectId Project/Agent Id. - * @param audioFilePath The audio file to be processed. - * @param sessionId Identifier of the DetectIntent session. - * @param languageCode Language code of the query. - * @return The List of StreamingDetectIntentResponses to the input audio inputs. - */ - public static List detectIntentStream( - String projectId, - String audioFilePath, - String sessionId, - String languageCode) throws Throwable { - // Start bi-directional StreamingDetectIntent stream. - final CountDownLatch notification = new CountDownLatch(1); - final List responseThrowables = new ArrayList<>(); - final List responses = new ArrayList<>(); + static void detectIntentStream(String projectId, String audioFilePath, String sessionId) { + // String projectId = "YOUR_PROJECT_ID"; + // String audioFilePath = "path_to_your_audio_file"; + // Using the same `sessionId` between requests allows continuation of the conversation. + // String sessionId = "Identifier of the DetectIntent session"; // Instantiates a client try (SessionsClient sessionsClient = SessionsClient.create()) { // Set the session name using the sessionId (UUID) and projectID (my-project-id) SessionName session = SessionName.of(projectId, sessionId); - System.out.println("Session Path: " + session.toString()); + // Instructs the speech recognizer how to process the audio content. // Note: hard coding audioEncoding and sampleRateHertz for simplicity. // Audio encoding of the audio content sent in the query request. - AudioEncoding audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16; - int sampleRateHertz = 16000; - - // Instructs the speech recognizer how to process the audio content. InputAudioConfig inputAudioConfig = InputAudioConfig.newBuilder() - .setAudioEncoding(audioEncoding) // audioEncoding = AudioEncoding.AUDIO_ENCODING_LINEAR_16 - .setLanguageCode(languageCode) // languageCode = "en-US" - .setSampleRateHertz(sampleRateHertz) // sampleRateHertz = 16000 + .setAudioEncoding(AudioEncoding.AUDIO_ENCODING_LINEAR_16) + .setLanguageCode("en-US") // languageCode = "en-US" + .setSampleRateHertz(16000) // sampleRateHertz = 16000 .build(); - ApiStreamObserver responseObserver = - new ApiStreamObserver() { - @Override - public void onNext(StreamingDetectIntentResponse response) { - // Do something when receive a response - responses.add(response); - } - - @Override - public void onError(Throwable t) { - // Add error-handling - responseThrowables.add(t); - } - - @Override - public void onCompleted() { - // Do something when complete. - notification.countDown(); - } - }; - - // Performs the streaming detect intent callable request - ApiStreamObserver requestObserver = - sessionsClient.streamingDetectIntentCallable().bidiStreamingCall(responseObserver); - // Build the query with the InputAudioConfig QueryInput queryInput = QueryInput.newBuilder().setAudioConfig(inputAudioConfig).build(); - try (FileInputStream audioStream = new FileInputStream(audioFilePath)) { - // The first request contains the configuration - StreamingDetectIntentRequest request = StreamingDetectIntentRequest.newBuilder() - .setSession(session.toString()) - .setQueryInput(queryInput) - .build(); + // Create the Bidirectional stream + BidiStream bidiStream = + sessionsClient.streamingDetectIntentCallable().call(); - // Make the first request - requestObserver.onNext(request); + // The first request must **only** contain the audio configuration: + bidiStream.send(StreamingDetectIntentRequest.newBuilder() + .setSession(session.toString()) + .setQueryInput(queryInput) + .build()); + try (FileInputStream audioStream = new FileInputStream(audioFilePath)) { + // Subsequent requests must **only** contain the audio data. // Following messages: audio chunks. We just read the file in fixed-size chunks. In reality // you would split the user input by time. byte[] buffer = new byte[4096]; int bytes; while ((bytes = audioStream.read(buffer)) != -1) { - requestObserver.onNext( + bidiStream.send( StreamingDetectIntentRequest.newBuilder() .setInputAudio(ByteString.copyFrom(buffer, 0, bytes)) .build()); } - } catch (RuntimeException e) { - // Cancel stream. - requestObserver.onError(e); - } - // Half-close the stream. - requestObserver.onCompleted(); - // Wait for the final response (without explicit timeout). - notification.await(); - // Process errors/responses. - if (!responseThrowables.isEmpty()) { - throw responseThrowables.get(0); - } - if (responses.isEmpty()) { - throw new RuntimeException("No response from Dialogflow."); } - for (StreamingDetectIntentResponse response : responses) { - if (response.hasRecognitionResult()) { - System.out.format( - "Intermediate transcript: '%s'\n", response.getRecognitionResult().getTranscript()); - } - } + // Tell the service you are done sending data + bidiStream.closeSend(); - // Display the last query result - QueryResult queryResult = responses.get(responses.size() - 1).getQueryResult(); - System.out.println("===================="); - System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); - System.out.format("Detected Intent: %s (confidence: %f)\n", - queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); - System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); + for (StreamingDetectIntentResponse response : bidiStream) { + QueryResult queryResult = response.getQueryResult(); + System.out.println("===================="); + System.out.format("Intent Display Name: %s\n", queryResult.getIntent().getDisplayName()); + System.out.format("Query Text: '%s'\n", queryResult.getQueryText()); + System.out.format("Detected Intent: %s (confidence: %f)\n", + queryResult.getIntent().getDisplayName(), queryResult.getIntentDetectionConfidence()); + System.out.format("Fulfillment Text: '%s'\n", queryResult.getFulfillmentText()); - return responses; + } + } catch (IOException e) { + e.printStackTrace(); } } - // [END dialogflow_detect_intent_streaming] } +// [END dialogflow_detect_intent_streaming] diff --git a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithSentimentAnalysis.java b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithSentimentAnalysis.java index b75e1a541cd..3005847a1a5 100644 --- a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithSentimentAnalysis.java +++ b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithSentimentAnalysis.java @@ -16,16 +16,16 @@ package com.example.dialogflow; -import com.google.cloud.dialogflow.v2beta1.DetectIntentRequest; -import com.google.cloud.dialogflow.v2beta1.DetectIntentResponse; -import com.google.cloud.dialogflow.v2beta1.QueryInput; -import com.google.cloud.dialogflow.v2beta1.QueryParameters; -import com.google.cloud.dialogflow.v2beta1.QueryResult; -import com.google.cloud.dialogflow.v2beta1.SentimentAnalysisRequestConfig; -import com.google.cloud.dialogflow.v2beta1.SessionName; -import com.google.cloud.dialogflow.v2beta1.SessionsClient; -import com.google.cloud.dialogflow.v2beta1.TextInput; -import com.google.cloud.dialogflow.v2beta1.TextInput.Builder; +import com.google.cloud.dialogflow.v2.DetectIntentRequest; +import com.google.cloud.dialogflow.v2.DetectIntentResponse; +import com.google.cloud.dialogflow.v2.QueryInput; +import com.google.cloud.dialogflow.v2.QueryParameters; +import com.google.cloud.dialogflow.v2.QueryResult; +import com.google.cloud.dialogflow.v2.SentimentAnalysisRequestConfig; +import com.google.cloud.dialogflow.v2.SessionName; +import com.google.cloud.dialogflow.v2.SessionsClient; +import com.google.cloud.dialogflow.v2.TextInput; +import com.google.cloud.dialogflow.v2.TextInput.Builder; import com.google.common.collect.Maps; import java.util.List; diff --git a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithTextToSpeechResponse.java b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithTextToSpeechResponse.java index da053d1017d..c7387364334 100644 --- a/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithTextToSpeechResponse.java +++ b/dialogflow/cloud-client/src/main/java/com/example/dialogflow/DetectIntentWithTextToSpeechResponse.java @@ -16,16 +16,16 @@ package com.example.dialogflow; -import com.google.cloud.dialogflow.v2beta1.DetectIntentRequest; -import com.google.cloud.dialogflow.v2beta1.DetectIntentResponse; -import com.google.cloud.dialogflow.v2beta1.OutputAudioConfig; -import com.google.cloud.dialogflow.v2beta1.OutputAudioEncoding; -import com.google.cloud.dialogflow.v2beta1.QueryInput; -import com.google.cloud.dialogflow.v2beta1.QueryResult; -import com.google.cloud.dialogflow.v2beta1.SessionName; -import com.google.cloud.dialogflow.v2beta1.SessionsClient; -import com.google.cloud.dialogflow.v2beta1.TextInput; -import com.google.cloud.dialogflow.v2beta1.TextInput.Builder; +import com.google.cloud.dialogflow.v2.DetectIntentRequest; +import com.google.cloud.dialogflow.v2.DetectIntentResponse; +import com.google.cloud.dialogflow.v2.OutputAudioConfig; +import com.google.cloud.dialogflow.v2.OutputAudioEncoding; +import com.google.cloud.dialogflow.v2.QueryInput; +import com.google.cloud.dialogflow.v2.QueryResult; +import com.google.cloud.dialogflow.v2.SessionName; +import com.google.cloud.dialogflow.v2.SessionsClient; +import com.google.cloud.dialogflow.v2.TextInput; +import com.google.cloud.dialogflow.v2.TextInput.Builder; import com.google.common.collect.Maps; import java.util.List; diff --git a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentStreamIT.java b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentStreamIT.java index a1d6b8c080a..21499647662 100644 --- a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentStreamIT.java +++ b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentStreamIT.java @@ -16,14 +16,12 @@ package com.example.dialogflow; -import static org.junit.Assert.assertTrue; - -import com.google.cloud.dialogflow.v2.StreamingDetectIntentResponse; +import static org.junit.Assert.assertThat; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.PrintStream; -import java.util.List; - +import org.hamcrest.CoreMatchers; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -37,32 +35,35 @@ @SuppressWarnings("checkstyle:abbreviationaswordinname") public class DetectIntentStreamIT { + private ByteArrayOutputStream bout; + private static String audioFilePath = "resources/book_a_room.wav"; private static String PROJECT_ID = System.getenv().get("GOOGLE_CLOUD_PROJECT"); private static String SESSION_ID = "fake_session_for_testing"; - private static String LANGUAGE_CODE = "en-US"; @Before public void setUp() { - System.setOut(new PrintStream(new ByteArrayOutputStream())); + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); } @After public void tearDown() { System.setOut(null); + bout.reset(); } @Test - public void testStreamingDetectIntentCallable() throws Throwable { - List response = DetectIntentStream.detectIntentStream( - PROJECT_ID, audioFilePath, SESSION_ID, LANGUAGE_CODE); - assertTrue(response.size() > 0); - assertTrue(response.stream().anyMatch(i -> i - .getQueryResult() - .getIntent() - .getDisplayName().equals("room.reservation"))); - assertTrue(response.stream().anyMatch(i -> i - .getRecognitionResult() - .getTranscript().contains("book"))); + public void testStreamingDetectIntentCallable() { + DetectIntentStream.detectIntentStream( + PROJECT_ID, audioFilePath, SESSION_ID); + + String output = bout.toString(); + + assertThat(output, CoreMatchers.containsString( + "Intent Display Name: room.reservation")); + + assertThat(output, CoreMatchers.containsString( + "book")); } } diff --git a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentWithSentimentAndTextToSpeechIT.java b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentWithSentimentAndTextToSpeechIT.java index a427f95aa50..bef351a10f6 100644 --- a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentWithSentimentAndTextToSpeechIT.java +++ b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/DetectIntentWithSentimentAndTextToSpeechIT.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import com.google.cloud.dialogflow.v2beta1.QueryResult; +import com.google.cloud.dialogflow.v2.QueryResult; import java.io.ByteArrayOutputStream; import java.io.PrintStream; diff --git a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/KnowledgeBaseManagementIT.java b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/KnowledgeBaseManagementIT.java index d6bdab305e2..180678dcea5 100644 --- a/dialogflow/cloud-client/src/test/java/com/example/dialogflow/KnowledgeBaseManagementIT.java +++ b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/KnowledgeBaseManagementIT.java @@ -55,7 +55,8 @@ public class KnowledgeBaseManagementIT { private static List TEXTS = ImmutableList .of("How do I sign up?", "Is my data redundant?", "Where can I find pricing information?", - "Where is my data stored?", "What are my support options?"); + "Where is my data stored?", "What are my support options?", + "How can I maximize the availability of my data?"); @Before public void setUp() { @@ -167,11 +168,10 @@ public void testDetectIntentKnowledge() throws Exception { for (String text : TEXTS) { KnowledgeAnswers knowledgeAnswers = allAnswers.get(text); if (knowledgeAnswers.getAnswersCount() > 0) { - answersFound++; Answer answer = knowledgeAnswers.getAnswers(0); - assertEquals(text, answer.getFaqQuestion()); - assertEquals(document.getName(), answer.getSource()); - assertThat(answer.getAnswer()).contains("Cloud Storage"); + if (text.equals(answer.getFaqQuestion()) && document.getName().equals(answer.getSource())) { + answersFound++; + } } } // To make the test less flaky, check that half of the texts got a result. diff --git a/dlp/pom.xml b/dlp/pom.xml index 3317da3ccad..5ebc975107b 100644 --- a/dlp/pom.xml +++ b/dlp/pom.xml @@ -29,7 +29,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/endpoints/getting-started/clients/pom.xml b/endpoints/getting-started/clients/pom.xml index 1e552e43c35..6040ceda998 100644 --- a/endpoints/getting-started/clients/pom.xml +++ b/endpoints/getting-started/clients/pom.xml @@ -15,7 +15,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/endpoints/multiple-versions/pom.xml b/endpoints/multiple-versions/pom.xml index c0329ef52f5..422772fc036 100644 --- a/endpoints/multiple-versions/pom.xml +++ b/endpoints/multiple-versions/pom.xml @@ -22,11 +22,14 @@ com.example.endpoints endpoints + - doc-samples - com.google.cloud - 1.0.0 - ../.. + com.google.cloud.samples + shared-configuration + 1.0.11 diff --git a/errorreporting/pom.xml b/errorreporting/pom.xml index 46d04f56786..3cf13fa80af 100644 --- a/errorreporting/pom.xml +++ b/errorreporting/pom.xml @@ -27,7 +27,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/firestore/pom.xml b/firestore/pom.xml index bb29d66b0e5..ed5a9dba358 100644 --- a/firestore/pom.xml +++ b/firestore/pom.xml @@ -32,7 +32,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 1.8 @@ -45,7 +45,7 @@ com.google.cloud google-cloud-firestore - 1.0.0 + 1.2.0 diff --git a/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java b/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java index 0b152f18097..fede3d73c8c 100644 --- a/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java +++ b/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java @@ -17,11 +17,9 @@ package com.example.firestore.snippets; import com.example.firestore.snippets.model.City; - import com.google.api.core.ApiFuture; import com.google.api.core.ApiFutures; import com.google.cloud.firestore.CollectionReference; -import com.google.cloud.firestore.DocumentReference; import com.google.cloud.firestore.DocumentSnapshot; import com.google.cloud.firestore.Firestore; import com.google.cloud.firestore.Query; @@ -29,11 +27,9 @@ import com.google.cloud.firestore.QueryDocumentSnapshot; import com.google.cloud.firestore.QuerySnapshot; import com.google.cloud.firestore.WriteResult; - -import com.google.firestore.v1beta1.Document; -import com.google.protobuf.Api; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -383,4 +379,66 @@ List paginateCursor() throws InterruptedException, ExecutionException, Ti // [END fs_paginate_cursor] return Arrays.asList(firstPage, secondPage); } + + void collectionGroupQuery() throws ExecutionException, InterruptedException { + //CHECKSTYLE OFF: Indentation + //CHECKSTYLE OFF: RightCurlyAlone + // [START fs_collection_group_query_data_setup] + CollectionReference cities = db.collection("cities"); + + final List> futures = Arrays.asList( + cities.document("SF").collection("landmarks").document().set(new HashMap() {{ + put("name", "Golden Gate Bridge"); + put("type", "bridge"); + }}), + cities.document("SF").collection("landmarks").document().set(new HashMap() {{ + put("name", "Legion of Honor"); + put("type", "museum"); + }}), + cities.document("LA").collection("landmarks").document().set(new HashMap() {{ + put("name", "Griffith Park"); + put("type", "park"); + }}), + cities.document("LA").collection("landmarks").document().set(new HashMap() {{ + put("name", "The Getty"); + put("type", "museum"); + }}), + cities.document("DC").collection("landmarks").document().set(new HashMap() {{ + put("name", "Lincoln Memorial"); + put("type", "memorial"); + }}), + cities.document("DC").collection("landmarks").document().set(new HashMap() {{ + put("name", "National Air and Space Museum"); + put("type", "museum"); + }}), + cities.document("TOK").collection("landmarks").document().set(new HashMap() {{ + put("name", "Ueno Park"); + put("type", "park"); + }}), + cities.document("TOK").collection("landmarks").document().set(new HashMap() {{ + put("name", "National Museum of Nature and Science"); + put("type", "museum"); + }}), + cities.document("BJ").collection("landmarks").document().set(new HashMap() {{ + put("name", "Jingshan Park"); + put("type", "park"); + }}), + cities.document("BJ").collection("landmarks").document().set(new HashMap() {{ + put("name", "Beijing Ancient Observatory"); + put("type", "museum"); + }}) + ); + final List landmarks = ApiFutures.allAsList(futures).get(); + // [END fs_collection_group_query_data_setup] + + // [START fs_collection_group_query] + final Query museums = db.collectionGroup("landmarks").whereEqualTo("type", "museum"); + final ApiFuture querySnapshot = museums.get(); + for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { + System.out.println(document.getId()); + } + // [END fs_collection_group_query] + //CHECKSTYLE ON: RightCurlyAlone + //CHECKSTYLE ON: Indentation + } } diff --git a/firestore/src/main/java/com/example/firestore/snippets/model/City.java b/firestore/src/main/java/com/example/firestore/snippets/model/City.java index 864508d3866..48a41145a16 100644 --- a/firestore/src/main/java/com/example/firestore/snippets/model/City.java +++ b/firestore/src/main/java/com/example/firestore/snippets/model/City.java @@ -161,4 +161,9 @@ public boolean equals(Object obj) { && Objects.equals(capital, city.capital) && Objects.equals(regions, city.regions); } + + @Override + public int hashCode() { + return Objects.hash(name, state, country, capital, population, regions); + } } diff --git a/flexible/analytics/pom.xml b/flexible/analytics/pom.xml index 98450f0d369..bb1101da1ea 100644 --- a/flexible/analytics/pom.xml +++ b/flexible/analytics/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/async-rest/pom.xml b/flexible/async-rest/pom.xml index ed662475947..c97ff372845 100644 --- a/flexible/async-rest/pom.xml +++ b/flexible/async-rest/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/cloud-tasks/pom.xml b/flexible/cloud-tasks/pom.xml index 119e6a21ee4..9657af7db67 100644 --- a/flexible/cloud-tasks/pom.xml +++ b/flexible/cloud-tasks/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/cloudsql/pom.xml b/flexible/cloudsql/pom.xml index c9ef9b1075f..b0f688535af 100644 --- a/flexible/cloudsql/pom.xml +++ b/flexible/cloudsql/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/cloudstorage/pom.xml b/flexible/cloudstorage/pom.xml index b71c733d48a..cc9c2a871bc 100644 --- a/flexible/cloudstorage/pom.xml +++ b/flexible/cloudstorage/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/cron/pom.xml b/flexible/cron/pom.xml index 0046b8f7743..d7c9e969186 100644 --- a/flexible/cron/pom.xml +++ b/flexible/cron/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/datastore/pom.xml b/flexible/datastore/pom.xml index a1954f6d23f..5204ff774a0 100644 --- a/flexible/datastore/pom.xml +++ b/flexible/datastore/pom.xml @@ -20,11 +20,14 @@ com.example.flexible flexible-datastore + - appengine-flexible - com.google.cloud - 1.0.0 - .. + com.google.cloud.samples + shared-configuration + 1.0.11 diff --git a/flexible/disk/pom.xml b/flexible/disk/pom.xml index 930dbc5bbb4..095cdacd239 100644 --- a/flexible/disk/pom.xml +++ b/flexible/disk/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/errorreporting/pom.xml b/flexible/errorreporting/pom.xml index 0aebfec3abb..808bbda3a66 100644 --- a/flexible/errorreporting/pom.xml +++ b/flexible/errorreporting/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/extending-runtime/pom.xml b/flexible/extending-runtime/pom.xml index 02b419df0d7..e3aafe9be8b 100644 --- a/flexible/extending-runtime/pom.xml +++ b/flexible/extending-runtime/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/gaeinfo/pom.xml b/flexible/gaeinfo/pom.xml index 03585d2d1a6..3ea2c929ee0 100644 --- a/flexible/gaeinfo/pom.xml +++ b/flexible/gaeinfo/pom.xml @@ -27,7 +27,7 @@ Copyright 2017 Google Inc. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/helloworld/pom.xml b/flexible/helloworld/pom.xml index 4692ef6cea2..27072abf641 100644 --- a/flexible/helloworld/pom.xml +++ b/flexible/helloworld/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/mailgun/pom.xml b/flexible/mailgun/pom.xml index f6d79b603ff..63327623ea4 100644 --- a/flexible/mailgun/pom.xml +++ b/flexible/mailgun/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/mailjet/pom.xml b/flexible/mailjet/pom.xml index 3fe29a459c9..ae3c23b2988 100644 --- a/flexible/mailjet/pom.xml +++ b/flexible/mailjet/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/memcache/pom.xml b/flexible/memcache/pom.xml index 4de2cddb3d6..63a7fd39f11 100644 --- a/flexible/memcache/pom.xml +++ b/flexible/memcache/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/pom.xml b/flexible/pom.xml deleted file mode 100644 index 39dd86a9876..00000000000 --- a/flexible/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - 4.0.0 - 1.0.0 - - com.google.cloud - appengine-flexible - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - - analytics - async-rest - cloud-tasks - cloudsql - cloudstorage - cron - datastore - disk - errorreporting - extending-runtime - gaeinfo - helloworld - mailgun - mailjet - memcache - postgres - pubsub - sendgrid - sparkjava - static-files - twilio - - - - diff --git a/flexible/postgres/pom.xml b/flexible/postgres/pom.xml index 167a59edf4e..ccc9187be61 100644 --- a/flexible/postgres/pom.xml +++ b/flexible/postgres/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/pubsub/pom.xml b/flexible/pubsub/pom.xml index 91970181892..d8009c91516 100644 --- a/flexible/pubsub/pom.xml +++ b/flexible/pubsub/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/sendgrid/pom.xml b/flexible/sendgrid/pom.xml index fea3f0a670b..10a6c3778aa 100644 --- a/flexible/sendgrid/pom.xml +++ b/flexible/sendgrid/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/sparkjava/pom.xml b/flexible/sparkjava/pom.xml index 30aeea0481c..b2d39f82fbe 100644 --- a/flexible/sparkjava/pom.xml +++ b/flexible/sparkjava/pom.xml @@ -29,7 +29,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/static-files/pom.xml b/flexible/static-files/pom.xml index 360a8dc12dc..8e8cf6ca16a 100644 --- a/flexible/static-files/pom.xml +++ b/flexible/static-files/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/flexible/twilio/pom.xml b/flexible/twilio/pom.xml index a97e9bf2b6f..17d4210b0f5 100644 --- a/flexible/twilio/pom.xml +++ b/flexible/twilio/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/healthcare/v1beta1/DicomStoreSearchInstances.ps1 b/healthcare/v1beta1/DicomStoreSearchInstances.ps1 new file mode 100644 index 00000000000..57abb3707d8 --- /dev/null +++ b/healthcare/v1beta1/DicomStoreSearchInstances.ps1 @@ -0,0 +1,22 @@ +# Copyright 2019 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. + +$cred = gcloud auth print-access-token +$headers = @{ Authorization = "Bearer $cred" } + +Invoke-RestMethod ` + -Method Get ` + -Headers $headers ` + -ContentType: "application/json; charset=utf-8" ` + -Uri "https://healthcare.googleapis.com/v1alpha1/projects/dzlier-work/locations/us-central1/datasets/dataset-13c3/dicomStores/dicom-store-13c3/dicomWeb/instances" \ No newline at end of file diff --git a/healthcare/v1beta1/dicom-store-search-instances.sh b/healthcare/v1beta1/dicom-store-search-instances.sh new file mode 100644 index 00000000000..9bb26e1a294 --- /dev/null +++ b/healthcare/v1beta1/dicom-store-search-instances.sh @@ -0,0 +1,18 @@ +# Copyright 2019 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. + +curl -X GET \ + -H "Authorization: Bearer "$(gcloud auth print-access-token) \ + -H "Content-Type: application/dicom+json; charset=utf-8" \ + "https://healthcare.googleapis.com/v1beta1/projects/dzlier-work/locations/us-central1/datasets/dataset-13c3/dicomStores/dicom-store-13c3/dicomWeb/instances" \ No newline at end of file diff --git a/healthcare/v1beta1/pom.xml b/healthcare/v1beta1/pom.xml new file mode 100644 index 00000000000..a65e3f9cfc8 --- /dev/null +++ b/healthcare/v1beta1/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + com.google.samples + healthcare-samples + 1.0-SNAPSHOT + jar + + + + com.google.cloud.samples + shared-configuration + 1.0.10 + + + + UTF-8 + 1.8 + 1.8 + + + + 3.5 + + + + + + com.google.apis + google-api-services-healthcare + v1beta1-rev20190420-1.28.0 + + + com.google.api-client + google-api-client + 1.28.0 + + + com.google.cloud + google-cloud-core + 1.71.0 + compile + + + + + + com.google.truth + truth + 0.44 + test + + + junit + junit + 4.12 + + + org.apache.httpcomponents + httpmime + 4.5.8 + + + \ No newline at end of file diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetCreate.java new file mode 100644 index 00000000000..6a776b94ee2 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetCreate.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_create_dataset] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Dataset; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import java.io.IOException; +import java.util.Collections; + +public class DatasetCreate { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetCreate(String projectId, String regionId, String datasetId) + throws IOException { + // String projectId = "your-project-id"; + // String regionId = "us-central1"; + // String datasetId = "your-dataset-id"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the dataset to be created. + Dataset dataset = new Dataset(); + dataset.setTimeZone("America/Chicago"); + + // Create request and configure any parameters. + String parentName = String.format("projects/%s/locations/%s", projectId, regionId); + Datasets.Create request = client.projects().locations().datasets().create(parentName, dataset); + request.setDatasetId(datasetId); + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + System.out.println(operation.toPrettyString()); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println("Dataset created. Response content: " + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s\n", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_create_dataset] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDeIdentify.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDeIdentify.java new file mode 100644 index 00000000000..7617450259b --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDeIdentify.java @@ -0,0 +1,111 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_deidentify_dataset] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.DeidentifyConfig; +import com.google.api.services.healthcare.v1beta1.model.DeidentifyDatasetRequest; +import com.google.api.services.healthcare.v1beta1.model.DicomConfig; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import com.google.api.services.healthcare.v1beta1.model.TagFilterList; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; + +public class DatasetDeIdentify { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetDeIdentify(String srcDatasetName, String destDatasetName) + throws IOException { + // String srcDatasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-src-dataset-id"); + // String destDatasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dest-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure what information needs to be De-Identified. + // For more information on de-identifying using tags, please see the following: + // https://cloud.google.com/healthcare/docs/how-tos/dicom-deidentify#de-identification_using_tags + TagFilterList tags = new TagFilterList().setTags(Arrays.asList("PatientID")); + DicomConfig dicomConfig = new DicomConfig().setKeepList(tags); + DeidentifyConfig config = new DeidentifyConfig().setDicom(dicomConfig); + + // Create the de-identify request and configure any parameters. + DeidentifyDatasetRequest deidentifyRequest = + new DeidentifyDatasetRequest().setDestinationDataset(destDatasetName).setConfig(config); + Datasets.Deidentify request = + client.projects().locations().datasets().deidentify(srcDatasetName, deidentifyRequest); + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println( + "De-identified Dataset created. Response content: " + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_deidentify_dataset] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDelete.java new file mode 100644 index 00000000000..ba29dff0d6a --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDelete.java @@ -0,0 +1,74 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_delete_dataset] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class DatasetDelete { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetDelete(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Datasets.Delete request = client.projects().locations().datasets().delete(datasetName); + + // Execute the request and process the results. + request.execute(); + System.out.println("Dataset deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_delete_dataset] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGet.java new file mode 100644 index 00000000000..da55aef5355 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGet.java @@ -0,0 +1,75 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_get_dataset] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Dataset; +import java.io.IOException; +import java.util.Collections; + +public class DatasetGet { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetGet(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Datasets.Get request = client.projects().locations().datasets().get(datasetName); + + // Execute the request and process the results. + Dataset dataset = request.execute(); + System.out.println("Dataset retrieved: \n" + dataset.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_dataset] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGetIamPolicy.java new file mode 100644 index 00000000000..61ffe119da5 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGetIamPolicy.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_dataset_get_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import java.io.IOException; +import java.util.Collections; + +public class DatasetGetIamPolicy { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetGetIamPolicy(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Datasets.GetIamPolicy request = + client.projects().locations().datasets().getIamPolicy(datasetName); + + // Execute the request and process the results. + Policy policy = request.execute(); + System.out.println("Dataset IAMPolicy retrieved: \n" + policy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dataset_get_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetList.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetList.java new file mode 100644 index 00000000000..34c44fa8fa5 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetList.java @@ -0,0 +1,99 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_list_datasets] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Dataset; +import com.google.api.services.healthcare.v1beta1.model.ListDatasetsResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DatasetList { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetList(String projectId, String regionId) throws IOException { + // String projectId = "your-project-id"; + // String regionId = "us-central1"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Results are paginated, so multiple queries may be required. + String parentName = String.format("projects/%s/locations/%s", projectId, regionId); + String pageToken = null; + List datasets = new ArrayList<>(); + do { + // Create request and configure any parameters. + Datasets.List request = + client + .projects() + .locations() + .datasets() + .list(parentName) + .setPageSize(100) // Specify pageSize up to 1000 + .setPageToken(pageToken); + + // Execute response and collect results. + ListDatasetsResponse response = request.execute(); + datasets.addAll(response.getDatasets()); + + // Update the page token for the next request. + pageToken = response.getNextPageToken(); + } while (pageToken != null); + + // Print results. + System.out.printf("Retrieved %s datasets: \n", datasets.size()); + for (Dataset data : datasets) { + System.out.println("\t" + data.toPrettyString()); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_list_datasets] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetPatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetPatch.java new file mode 100644 index 00000000000..5bc686e085a --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetPatch.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_patch_dataset] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Dataset; +import java.io.IOException; +import java.util.Collections; + +public class DatasetPatch { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetPatch(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Fetch the initial state of the dataset. + Datasets.Get getRequest = client.projects().locations().datasets().get(datasetName); + Dataset dataset = getRequest.execute(); + + // Update the Dataset fields as needed as needed. For a full list of dataset fields, see: + // https://cloud.google.com/healthcare/docs/reference/rest/v1beta1/projects.locations.datasets#Dataset + dataset.setTimeZone("America/New_York"); + + // Create request and configure any parameters. + Datasets.Patch request = + client + .projects() + .locations() + .datasets() + .patch(datasetName, dataset) + .setUpdateMask("timeZone"); + + // Execute the request and process the results. + dataset = request.execute(); + System.out.println("Dataset patched: \n" + dataset.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_patch_dataset] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetSetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetSetIamPolicy.java new file mode 100644 index 00000000000..2f608e59460 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetSetIamPolicy.java @@ -0,0 +1,88 @@ +/* + * Copyright 2019 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 snippets.healthcare.datasets; + +// [START healthcare_dataset_set_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Binding; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import com.google.api.services.healthcare.v1beta1.model.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; + +public class DatasetSetIamPolicy { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void datasetSetIamPolicy(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the IAMPolicy to apply to the dataset. + // For more information on understanding IAM roles, see the following: + // https://cloud.google.com/iam/docs/understanding-roles + Binding binding = + new Binding() + .setRole("roles/healthcare.datasetViewer") + .setMembers(Arrays.asList("domain:google.com")); + Policy policy = new Policy().setBindings(Arrays.asList(binding)); + SetIamPolicyRequest policyRequest = new SetIamPolicyRequest().setPolicy(policy); + + // Create request and configure any parameters. + Datasets.SetIamPolicy request = + client.projects().locations().datasets().setIamPolicy(datasetName, policyRequest); + + // Execute the request and process the results. + Policy updatedPolicy = request.execute(); + System.out.println("Dataset policy has been updated: " + updatedPolicy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dataset_set_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreCreate.java new file mode 100644 index 00000000000..af7cc4a7555 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreCreate.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_create_dicom_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.DicomStore; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class DicomStoreCreate { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreCreate(String datasetName, String dicomStoreId) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the dicomStore to be created. + Map labels = new HashMap(); + labels.put("key1", "value1"); + labels.put("key2", "value2"); + DicomStore content = new DicomStore().setLabels(labels); + + // Create request and configure any parameters. + DicomStores.Create request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .create(datasetName, content) + .setDicomStoreId(dicomStoreId); + + // Execute the request and process the results. + DicomStore response = request.execute(); + System.out.println("DICOM store created: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_create_dicom_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreDelete.java new file mode 100644 index 00000000000..4205d40f15b --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreDelete.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_delete_dicom_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class DicomStoreDelete { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void deleteDicomStore(String dicomStoreName) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + DicomStores.Delete request = + client.projects().locations().datasets().dicomStores().delete(dicomStoreName); + + // Execute the request and process the results. + request.execute(); + System.out.println("DICOM store deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_delete_dicom_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreExport.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreExport.java new file mode 100644 index 00000000000..a092ee939d5 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreExport.java @@ -0,0 +1,108 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_export_dicom_instance] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.ExportDicomDataRequest; +import com.google.api.services.healthcare.v1beta1.model.GoogleCloudHealthcareV1beta1DicomGcsDestination; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import java.io.IOException; +import java.util.Collections; + +public class DicomStoreExport { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreExport(String dicomStoreName, String gcsUri) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String gcsUri = "gs://your-bucket-id/path/to/destination/dir" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure where the store will be exported too. + GoogleCloudHealthcareV1beta1DicomGcsDestination gcsDestination = + new GoogleCloudHealthcareV1beta1DicomGcsDestination().setUriPrefix(gcsUri); + ExportDicomDataRequest exportRequest = + new ExportDicomDataRequest().setGcsDestination(gcsDestination); + + // Create request and configure any parameters. + DicomStores.Export request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .export(dicomStoreName, exportRequest); + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println("DICOM store export complete." + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_export_dicom_instance] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGet.java new file mode 100644 index 00000000000..055e29a760c --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGet.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_get_dicom_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.DicomStore; +import java.io.IOException; +import java.util.Collections; + +public class DicomStoreGet { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomeStoreGet(String dicomStoreName) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + DicomStores.Get request = + client.projects().locations().datasets().dicomStores().get(dicomStoreName); + + // Execute the request and process the results. + DicomStore store = request.execute(); + System.out.println("DICOM store retrieved: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_dicom_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGetIamPolicy.java new file mode 100644 index 00000000000..f6f27f25a4d --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGetIamPolicy.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicom_store_get_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import java.io.IOException; +import java.util.Collections; + +public class DicomStoreGetIamPolicy { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreGetIamPolicy(String dicomStoreName) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + DicomStores.GetIamPolicy request = + client.projects().locations().datasets().dicomStores().getIamPolicy(dicomStoreName); + + // Execute the request and process the results. + Policy policy = request.execute(); + System.out.println("DICOM store IAMPolicy retrieved: \n" + policy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dicom_store_get_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreImport.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreImport.java new file mode 100644 index 00000000000..193d51215bd --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreImport.java @@ -0,0 +1,109 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_import_dicom_instance] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.GoogleCloudHealthcareV1beta1DicomGcsSource; +import com.google.api.services.healthcare.v1beta1.model.ImportDicomDataRequest; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import java.io.IOException; +import java.util.Collections; + +public class DicomStoreImport { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreImport(String dicomStoreName, String gcsUri) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String gcsUri = "gs://your-bucket-id/path/to/destination/dir" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure where the store should be imported from. + GoogleCloudHealthcareV1beta1DicomGcsSource gcsSource = + new GoogleCloudHealthcareV1beta1DicomGcsSource().setUri(gcsUri); + ImportDicomDataRequest importRequest = new ImportDicomDataRequest().setGcsSource(gcsSource); + + // Create request and configure any parameters. + DicomStores.CloudHealthcareImport request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .healthcareImport(dicomStoreName, importRequest); + + // Execute the request, wait for the operation to complete, and process the results. + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println("DICOM store import complete." + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_import_dicom_instance] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreList.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreList.java new file mode 100644 index 00000000000..a3b1139ad2b --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreList.java @@ -0,0 +1,100 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_list_dicom_stores] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.DicomStore; +import com.google.api.services.healthcare.v1beta1.model.ListDicomStoresResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DicomStoreList { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreList(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Results are paginated, so multiple queries may be required. + String pageToken = null; + List stores = new ArrayList<>(); + do { + // Create request and configure any parameters. + DicomStores.List request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .list(datasetName) + .setPageSize(100) // Specify pageSize up to 1000 + .setPageToken(pageToken); + + // Execute response and collect results. + ListDicomStoresResponse response = request.execute(); + stores.addAll(response.getDicomStores()); + + // Update the page token for the next request. + pageToken = response.getNextPageToken(); + } while (pageToken != null); + + // Print results. + System.out.printf("Retrieved %s DICOM stores: \n", stores.size()); + for (DicomStore data : stores) { + System.out.println("\t" + data.toPrettyString()); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_list_dicom_stores] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStorePatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStorePatch.java new file mode 100644 index 00000000000..8558b45d8f7 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStorePatch.java @@ -0,0 +1,93 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_patch_dicom_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.DicomStore; +import com.google.api.services.healthcare.v1beta1.model.NotificationConfig; +import java.io.IOException; +import java.util.Collections; + +public class DicomStorePatch { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void patchDicomStore(String dicomStoreName, String pubsubTopic) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String pubsubTopic = "your-pubsub-topic"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Fetch the initial state of the DICOM store. + DicomStores.Get getRequest = + client.projects().locations().datasets().dicomStores().get(dicomStoreName); + DicomStore store = getRequest.execute(); + + // Update the DicomStore fields as needed as needed. For a full list of DicomStore fields, see: + // https://cloud.google.com/healthcare/docs/reference/rest/v1beta1/projects.locations.datasets.dicomStores#DicomStore + store.setNotificationConfig(new NotificationConfig().setPubsubTopic(pubsubTopic)); + + // Create request and configure any parameters. + DicomStores.Patch request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .patch(dicomStoreName, store) + .setUpdateMask("notificationConfig"); + + // Execute the request and process the results. + store = request.execute(); + System.out.println("DICOM store patched: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_patch_dicom_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreSetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreSetIamPolicy.java new file mode 100644 index 00000000000..98d5c5c4f02 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreSetIamPolicy.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicom_store_set_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Binding; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import com.google.api.services.healthcare.v1beta1.model.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; + +public class DicomStoreSetIamPolicy { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomStoreSetIamPolicy(String dicomStoreName) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the IAMPolicy to apply to the store. + // For more information on understanding IAM roles, see the following: + // https://cloud.google.com/iam/docs/understanding-roles + Binding binding = + new Binding() + .setRole("roles/healthcare.dicomStoreAdmin") + .setMembers(Arrays.asList("domain:google.com")); + Policy policy = new Policy().setBindings(Arrays.asList(binding)); + SetIamPolicyRequest policyRequest = new SetIamPolicyRequest().setPolicy(policy); + + // Create request and configure any parameters. + DicomStores.SetIamPolicy request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .setIamPolicy(dicomStoreName, policyRequest); + + // Execute the request and process the results. + Policy updatedPolicy = request.execute(); + System.out.println("DICOM policy has been updated: " + updatedPolicy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dicom_store_set_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebDeleteStudy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebDeleteStudy.java new file mode 100644 index 00000000000..8e9fd9fb2ba --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebDeleteStudy.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicomweb_delete_study] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class DicomWebDeleteStudy { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomWebDeleteStudy(String dicomStoreName, String studyId) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String studyId = "your-study-id"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Studies.Delete request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .studies() + .delete(dicomStoreName, "studies/" + studyId); + + // Execute the request and process the results. + request.execute(); + System.out.println("DICOM study deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dicomweb_delete_study] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebRetrieveStudy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebRetrieveStudy.java new file mode 100644 index 00000000000..3569f0dfcfa --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebRetrieveStudy.java @@ -0,0 +1,98 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicomweb_retrieve_study] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores.Studies; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.stream.Collectors; + +public class DicomWebRetrieveStudy { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomWebRetrieveStudy(String dicomStoreName, String studyId) + throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String studyId = "your-study-id"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Studies.RetrieveStudy request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .studies() + .retrieveStudy(dicomStoreName, "studies/" + studyId); + + // Execute the request and process the results. + HttpResponse response = request.executeUnparsed(); + String content = new BufferedReader( + new InputStreamReader(response.getContent())).lines().collect(Collectors.joining("\n")); + if (!response.isSuccessStatusCode()) { + System.err.print(String.format( + "Exception storing DICOM instance: %s\n", response.getStatusMessage())); + System.out.println(content); + throw new RuntimeException(); + } + System.out.println("DICOM study retrieved: \n" + content); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dicomweb_retrieve_study] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebSearchForInstances.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebSearchForInstances.java new file mode 100644 index 00000000000..56e3ac2044a --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebSearchForInstances.java @@ -0,0 +1,82 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicomweb_search_instances] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.HttpResponse; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.DicomStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.util.Collections; + +public class DicomWebSearchForInstances { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomWebSearchForInstances(String dicomStoreName) throws IOException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + DicomStores.SearchForInstances request = + client + .projects() + .locations() + .datasets() + .dicomStores() + .searchForInstances(dicomStoreName, "instances"); + + // Execute the request and process the results. + HttpResponse response = request.executeUnparsed(); + System.out.println("Dicom store instances found: \n" + response.toString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_dicomweb_search_instances] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebStoreInstance.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebStoreInstance.java new file mode 100644 index 00000000000..c959634c473 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebStoreInstance.java @@ -0,0 +1,121 @@ +/* + * Copyright 2019 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 snippets.healthcare.dicom; + +// [START healthcare_dicomweb_store_instance] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.HttpClients; + +public class DicomWebStoreInstance { + private static final String DICOM_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void dicomWebStoreInstance(String dicomStoreName, String filePath) + throws IOException, URISyntaxException { + // String dicomStoreName = + // String.format( + // DICOM_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-dicom-id"); + // String filePath = "path/to/file.dcm"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/dicomWeb/studies", client.getRootUrl(), dicomStoreName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + // Load the data from file representing the study. + File f = new File(filePath); + byte[] dicomBytes = Files.readAllBytes(Paths.get(filePath)); + ByteArrayEntity requestEntity = new ByteArrayEntity(dicomBytes); + + HttpUriRequest request = RequestBuilder + .post(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type","application/dicom") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception storing DICOM instance: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("DICOM instance stored: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_dicomweb_store_instance] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java new file mode 100644 index 00000000000..6fb00284b4b --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java @@ -0,0 +1,91 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_create_fhir_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.FhirStore; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class FhirStoreCreate { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreCreate(String datasetName, String fhirStoreId) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + // String fhirStoreId = "your-fhir-id" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the FhirStore to be created. + Map labels = new HashMap(); + labels.put("key1", "value1"); + labels.put("key2", "value2"); + FhirStore content = new FhirStore().setLabels(labels); + + // Create request and configure any parameters. + FhirStores.Create request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .create(datasetName, content) + .setFhirStoreId(fhirStoreId); + + // Execute the request and process the results. + FhirStore response = request.execute(); + System.out.println("FHIR store created: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_create_fhir_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreDelete.java new file mode 100644 index 00000000000..ffa5a50bd16 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreDelete.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_delete_dicom_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class FhirStoreDelete { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreDelete(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + FhirStores.Delete request = + client.projects().locations().datasets().fhirStores().delete(fhirStoreName); + + // Execute the request and process the results. + request.execute(); + System.out.println("FHIR store deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_delete_dicom_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExecuteBundle.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExecuteBundle.java new file mode 100644 index 00000000000..def26ae2aa3 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExecuteBundle.java @@ -0,0 +1,116 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_fhir_execute_bundle] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirStoreExecuteBundle { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/dicomStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreExecuteBundle(String fhirStoreName, String data) + throws IOException, URISyntaxException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + // String data = "[{\"op\": \"add\", \"path\": \"/active\", \"value\": true}]"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + HttpClient httpClient = HttpClients.createDefault(); + String baseUri = String.format("%sv1beta1/%s/fhir", client.getRootUrl(), fhirStoreName); + URIBuilder uriBuilder = new URIBuilder(baseUri) + .setParameter("access_token", getAccessToken()); + StringEntity requestEntity = new StringEntity(data); + + HttpUriRequest request = RequestBuilder + .post() + .setUri(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception executing FHIR bundle: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.print("FHIR bundle executed: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_fhir_execute_bundle] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExport.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExport.java new file mode 100644 index 00000000000..5d9e32b68cb --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExport.java @@ -0,0 +1,104 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_export_fhir_resources] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.ExportResourcesRequest; +import com.google.api.services.healthcare.v1beta1.model.GoogleCloudHealthcareV1beta1FhirRestGcsDestination; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import java.io.IOException; +import java.util.Collections; + +public class FhirStoreExport { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreExport(String fhirStoreName, String gcsUri) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + // String gcsUri = "gs://your-bucket-id/path/to/destination/dir" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure where the store will be exported too. + GoogleCloudHealthcareV1beta1FhirRestGcsDestination gcsDestination = + new GoogleCloudHealthcareV1beta1FhirRestGcsDestination().setUriPrefix(gcsUri); + ExportResourcesRequest exportRequest = + new ExportResourcesRequest().setGcsDestination(gcsDestination); + + // Create request and configure any parameters. + FhirStores.Export request = + client.projects().locations().datasets().fhirStores().export(fhirStoreName, exportRequest); + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println("Fhir store export complete." + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_export_fhir_resources] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGet.java new file mode 100644 index 00000000000..70131f787ea --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGet.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_get_fhir_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.FhirStore; +import java.io.IOException; +import java.util.Collections; + +public class FhirStoreGet { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreGet(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + FhirStores.Get request = + client.projects().locations().datasets().fhirStores().get(fhirStoreName); + + // Execute the request and process the results. + FhirStore store = request.execute(); + System.out.println("FHIR store retrieved: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_fhir_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGetIamPolicy.java new file mode 100644 index 00000000000..5f1fd8ba2c8 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGetIamPolicy.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_fhir_store_get_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import java.io.IOException; +import java.util.Collections; + +public class FhirStoreGetIamPolicy { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreGetIamPolicy(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + FhirStores.GetIamPolicy request = + client.projects().locations().datasets().fhirStores().getIamPolicy(fhirStoreName); + + // Execute the request and process the results. + Policy policy = request.execute(); + System.out.println("FHIR store IAMPolicy retrieved: \n" + policy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_fhir_store_get_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java new file mode 100644 index 00000000000..6f79902a047 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java @@ -0,0 +1,108 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_import_fhir_resources] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.GoogleCloudHealthcareV1beta1FhirRestGcsSource; +import com.google.api.services.healthcare.v1beta1.model.ImportResourcesRequest; +import com.google.api.services.healthcare.v1beta1.model.Operation; +import java.io.IOException; +import java.util.Collections; + +public class FhirStoreImport { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreImport(String fhirStoreName, String gcsUri) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + // String gcsUri = "gs://your-bucket-id/path/to/destination/dir" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure where the store should be imported from. + GoogleCloudHealthcareV1beta1FhirRestGcsSource gcsSource = + new GoogleCloudHealthcareV1beta1FhirRestGcsSource().setUri(gcsUri); + ImportResourcesRequest importRequest = new ImportResourcesRequest().setGcsSource(gcsSource); + + // Create request and configure any parameters. + FhirStores.CloudHealthcareImport request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .healthcareImport(fhirStoreName, importRequest); + + // Execute the request, wait for the operation to complete, and process the results. + try { + Operation operation = request.execute(); + while (operation.getDone() == null || !operation.getDone()) { + // Update the status of the operation with another request. + Thread.sleep(500); // Pause for 500ms between requests. + operation = + client + .projects() + .locations() + .datasets() + .operations() + .get(operation.getName()) + .execute(); + } + System.out.println("FHIR store import complete: " + operation.getResponse()); + } catch (Exception ex) { + System.out.printf("Error during request execution: %s", ex.toString()); + ex.printStackTrace(System.out); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_import_fhir_resources] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreList.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreList.java new file mode 100644 index 00000000000..ced8015e967 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreList.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_list_fhir_stores] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.FhirStore; +import com.google.api.services.healthcare.v1beta1.model.ListFhirStoresResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class FhirStoreList { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreList(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Results are paginated, so multiple queries may be required. + String pageToken = null; + List stores = new ArrayList<>(); + do { + // Create request and configure any parameters. + FhirStores.List request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .list(fhirStoreName) + .setPageSize(100) // Specify pageSize up to 1000 + .setPageToken(pageToken); + + // Execute response and collect results. + ListFhirStoresResponse response = request.execute(); + stores.addAll(response.getFhirStores()); + + // Update the page token for the next request. + pageToken = response.getNextPageToken(); + } while (pageToken != null); + + // Print results. + System.out.printf("Retrieved %s Fhir stores: \n", stores.size()); + for (FhirStore data : stores) { + System.out.println("\t" + data.toPrettyString()); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_list_fhir_stores] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStorePatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStorePatch.java new file mode 100644 index 00000000000..2f6d66763d2 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStorePatch.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_patch_fhir_store] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.FhirStore; +import com.google.api.services.healthcare.v1beta1.model.NotificationConfig; +import java.io.IOException; +import java.util.Collections; + +public class FhirStorePatch { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStorePatch(String dicomStoreName, String pubsubTopic) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + // String pubsubTopic = "your-pubsub-topic"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Fetch the initial state of the FHIR store. + FhirStores.Get getRequest = + client.projects().locations().datasets().fhirStores().get(dicomStoreName); + FhirStore store = getRequest.execute(); + + // Update the FhirStore fields as needed as needed. For a full list of FhirStore fields, see: + // https://cloud.google.com/healthcare/docs/reference/rest/v1beta1/projects.locations.datasets.fhirStores#FhirStore + store.setNotificationConfig(new NotificationConfig().setPubsubTopic(pubsubTopic)); + + // Create request and configure any parameters. + FhirStores.Patch request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .patch(dicomStoreName, store) + .setUpdateMask("notificationConfig"); + + // Execute the request and process the results. + store = request.execute(); + System.out.println("Fhir store patched: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_patch_fhir_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreSetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreSetIamPolicy.java new file mode 100644 index 00000000000..7ac74a7dd10 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreSetIamPolicy.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir; + +// [START healthcare_fhir_store_set_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Binding; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import com.google.api.services.healthcare.v1beta1.model.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; + +public class FhirStoreSetIamPolicy { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirStoreSetIamPolicy(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the IAMPolicy to apply to the store. + // For more information on understanding IAM roles, see the following: + // https://cloud.google.com/iam/docs/understanding-roles + Binding binding = + new Binding() + .setRole("roles/healthcare.fhirResourceReader") + .setMembers(Arrays.asList("domain:google.com")); + Policy policy = new Policy().setBindings(Arrays.asList(binding)); + SetIamPolicyRequest policyRequest = new SetIamPolicyRequest().setPolicy(policy); + + // Create request and configure any parameters. + FhirStores.SetIamPolicy request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .setIamPolicy(fhirStoreName, policyRequest); + + // Execute the request and process the results. + Policy updatedPolicy = request.execute(); + System.out.println("FHIR policy has been updated: " + updatedPolicy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_fhir_store_set_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalDelete.java new file mode 100644 index 00000000000..d10b42b7b87 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalDelete.java @@ -0,0 +1,83 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_conditional_delete_resource] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores.Fhir.ConditionalDelete; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class FhirResourceConditionalDelete { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void conditionalDeleteFhirResource(String fhirStoreName) throws IOException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + String resourceType = "Patient"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + ConditionalDelete request = + client + .projects() + .locations() + .datasets() + .fhirStores() + .fhir() + .conditionalDelete(fhirStoreName, resourceType); + + // Execute the request and process the results. + request.execute(); + System.out.println("FHIR store conditionally deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_conditional_delete_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalPatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalPatch.java new file mode 100644 index 00000000000..50aff0ce7a8 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalPatch.java @@ -0,0 +1,124 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_conditional_patch_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceConditionalPatch { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceConditionalPatch( + String fhirStoreName, + String resourceType, + String fhirResourceId, + String data) throws IOException, URISyntaxException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + // String resourceType = "Patient"; + // String resourceType = "patient-123"; + // String data = "[{\"op\": \"replace\", \"path\": \"/active\", \"value\": false}]"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/fhir/%s", client.getRootUrl(), fhirStoreName, resourceType); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()) + .setParameter("_id", fhirResourceId); + StringEntity requestEntity = new StringEntity(data); + + HttpUriRequest request = RequestBuilder + .patch(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/json-patch+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception patching FHIR resource: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource conditionally patched: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_conditional_patch_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalUpdate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalUpdate.java new file mode 100644 index 00000000000..4206795a021 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalUpdate.java @@ -0,0 +1,121 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_conditional_update_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceConditionalUpdate { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceConditionalUpdate( + String fhirStoreName, + String resourceType, + String data) throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + // String resourceType = "Patient"; + // String data = "[{\"id\": \"resource-id\", \"language\": \"en_US\"}]"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/fhir/%s", client.getRootUrl(), fhirStoreName, resourceType); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + StringEntity requestEntity = new StringEntity(data); + + HttpUriRequest request = RequestBuilder + .put(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception updating FHIR resource: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource conditionally replaced: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_conditional_update_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceCreate.java new file mode 100644 index 00000000000..b3cc178c0bb --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceCreate.java @@ -0,0 +1,118 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_create_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceCreate { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceCreate(String fhirStoreName, String resourceType) + throws IOException, URISyntaxException { + // String fhirStoreName = + // String.format( + // FHIR_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-fhir-id"); + // String resourceType = "Patient"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/fhir/%s", client.getRootUrl(), fhirStoreName, resourceType); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + StringEntity requestEntity = new StringEntity( + "{\"resourceType\": \"" + resourceType + "\", \"language\": \"en\"}"); + + HttpUriRequest request = RequestBuilder + .post() + .setUri(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) { + System.err.print(String.format( + "Exception creating FHIR resource: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.print("FHIR resource created: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_create_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDelete.java new file mode 100644 index 00000000000..0502da9ebdd --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDelete.java @@ -0,0 +1,116 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_delete_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceDelete { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceDelete(String resourceName) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .delete() + .setUri(uriBuilder.build()) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + String errorMessage = String.format( + "Exception deleting FHIR resource: %s\n", response.getStatusLine().toString()); + System.err.print(errorMessage); + responseEntity.writeTo(System.err); + throw new RuntimeException(errorMessage); + } + System.out.println("FHIR resource deleted."); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_delete_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDeletePurge.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDeletePurge.java new file mode 100644 index 00000000000..660d525118a --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDeletePurge.java @@ -0,0 +1,116 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_delete_resource_purge] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceDeletePurge { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceDeletePurge(String resourceName) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/$purge", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .delete() + .setUri(uriBuilder.build()) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + String errorMessage = String.format( + "Exception purging FHIR resource: %s\n", response.getStatusLine().toString()); + System.err.print(errorMessage); + responseEntity.writeTo(System.err); + throw new RuntimeException(errorMessage); + } + System.out.println("FHIR resource purged."); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_delete_resource_purge] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGet.java new file mode 100644 index 00000000000..ad1a3264d92 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGet.java @@ -0,0 +1,111 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_get_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceGet { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceGet(String resourceName) throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .get() + .setUri(uriBuilder.build()) + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + String errorMessage = String.format( + "Exception retrieving FHIR resource: %s\n", response.getStatusLine().toString()); + System.err.print(errorMessage); + responseEntity.writeTo(System.err); + throw new RuntimeException(errorMessage); + } + System.out.println("FHIR resource retrieved: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_get_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetHistory.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetHistory.java new file mode 100644 index 00000000000..7374b95013c --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetHistory.java @@ -0,0 +1,114 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_get_resource_history] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceGetHistory { + private static final String FHIR_NAME = "projects/%s/locations/%s/datasets/%s/fhirStores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceGetHistory(String resourceName) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/_history", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .get() + .setUri(uriBuilder.build()) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception retrieving FHIR history: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource history retrieved: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_get_resource_history] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetMetadata.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetMetadata.java new file mode 100644 index 00000000000..239b57952c3 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetMetadata.java @@ -0,0 +1,79 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_get_metadata] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.FhirStores.Fhir.Capabilities; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.HttpBody; + +import java.io.IOException; +import java.util.Collections; + +public class FhirResourceGetMetadata { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceGetMetadata(String resourceName) throws IOException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Capabilities request = + client.projects().locations().datasets().fhirStores().fhir().capabilities(resourceName); + + // Execute the request and process the results. + HttpBody response = request.execute(); + System.out.println("FHIR resource metadata retrieved: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_metadata] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetPatientEverything.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetPatientEverything.java new file mode 100644 index 00000000000..2b12f1675c6 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetPatientEverything.java @@ -0,0 +1,115 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_get_patient_everything] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceGetPatientEverything { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceGetPatientEverything(String resourceName) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/$everything", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .get(uriBuilder.build()) + .addHeader("Content-Type", "application/json-patch+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception getting patient everythingresource: %s\n", + response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource search results: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_get_patient_everything] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourcePatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourcePatch.java new file mode 100644 index 00000000000..aa960c5aede --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourcePatch.java @@ -0,0 +1,118 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_patch_resource] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourcePatch { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourcePatch(String resourceName, String data) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + // String data = "[{\"op\": \"replace\", \"path\": \"/active\", \"value\": false}]"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + StringEntity requestEntity = new StringEntity(data); + + HttpUriRequest request = RequestBuilder + .patch(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/json-patch+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception patching FHIR resource: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource patched: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_patch_resource] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearch.java new file mode 100644 index 00000000000..057c7a60869 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearch.java @@ -0,0 +1,115 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_search_resources_get] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceSearch { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceSearch(String resourceName) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s", client.getRootUrl(), resourceName); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + + HttpUriRequest request = RequestBuilder + .get() + .setUri(uriBuilder.build()) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception searching FHIR resources: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource search results: "); + responseEntity.writeTo(System.out); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_search_resources_get] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearchPost.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearchPost.java new file mode 100644 index 00000000000..2b6340f8533 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearchPost.java @@ -0,0 +1,120 @@ +/* + * Copyright 2019 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 snippets.healthcare.fhir.resources; + +// [START healthcare_search_resources_post] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.HttpClients; + +public class FhirResourceSearchPost { + private static final String FHIR_NAME = + "projects/%s/locations/%s/datasets/%s/fhirStores/%s/fhir/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void fhirResourceSearchPost(String fhirStoreName, String resourceType) + throws IOException, URISyntaxException { + // String resourceName = + // String.format( + // FHIR_NAME, "project-id", "region-id", "dataset-id", "store-id", "fhir-id"); + // String resourceType = "Patient"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + HttpClient httpClient = HttpClients.createDefault(); + String uri = String.format( + "%sv1beta1/%s/fhir/%s/_search", client.getRootUrl(), fhirStoreName, resourceType); + URIBuilder uriBuilder = new URIBuilder(uri) + .setParameter("access_token", getAccessToken()); + StringEntity requestEntity = new StringEntity(""); + + HttpUriRequest request = RequestBuilder + .post() + .setUri(uriBuilder.build()) + .setEntity(requestEntity) + .addHeader("Content-Type", "application/fhir+json") + .addHeader("Accept-Charset", "utf-8") + .addHeader("Accept", "application/fhir+json; charset=utf-8") + .build(); + + // Execute the request and process the results. + HttpResponse response = httpClient.execute(request); + HttpEntity responseEntity = response.getEntity(); + if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { + System.err.print(String.format( + "Exception searching FHIR resources: %s\n", response.getStatusLine().toString())); + responseEntity.writeTo(System.err); + throw new RuntimeException(); + } + System.out.println("FHIR resource search results: "); + responseEntity.writeTo(System.out); + + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + private static String getAccessToken() throws IOException { + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + credential.refreshToken(); + return credential.getAccessToken(); + } +} +// [END healthcare_search_resources_post] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreCreate.java new file mode 100644 index 00000000000..17081a0ebfa --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreCreate.java @@ -0,0 +1,92 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_create_hl7v2_store] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Hl7V2Store; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class Hl7v2StoreCreate { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2StoreCreate(String datasetName, String hl7v2StoreId) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + // String hl7v2StoreId = "your-hl7v25-id" + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the store to be created. + Map labels = new HashMap<>(); + labels.put("key1", "value1"); + labels.put("key2", "value2"); + Hl7V2Store content = new Hl7V2Store().setLabels(labels); + + // Create request and configure any parameters. + Hl7V2Stores.Create request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .create(datasetName, content) + .setHl7V2StoreId(hl7v2StoreId); + + // Execute the request and process the results. + Hl7V2Store response = request.execute(); + System.out.println("Hl7V2Store store created: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_create_hl7v2_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreDelete.java new file mode 100644 index 00000000000..6f6c345d2ff --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreDelete.java @@ -0,0 +1,76 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_delete_hl7v2_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class Hl7v2StoreDelete { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2StoreDelete(String hl7v2StoreName) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Hl7V2Stores.Delete request = + client.projects().locations().datasets().hl7V2Stores().delete(hl7v2StoreName); + + // Execute the request and process the results. + request.execute(); + System.out.println("HL7v2 store deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_delete_hl7v2_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGet.java new file mode 100644 index 00000000000..7b4b61adf0a --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGet.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_get_hl7v2_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Hl7V2Store; +import java.io.IOException; +import java.util.Collections; + +public class Hl7v2StoreGet { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2eStoreGet(String hl7v2StoreName) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Hl7V2Stores.Get request = + client.projects().locations().datasets().hl7V2Stores().get(hl7v2StoreName); + + // Execute the request and process the results. + Hl7V2Store store = request.execute(); + System.out.println("HL7v2 store retrieved: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_hl7v2_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGetIamPolicy.java new file mode 100644 index 00000000000..4b639b53aa0 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGetIamPolicy.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_hl7v2_store_get_iam_policy] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import java.io.IOException; +import java.util.Collections; + +public class Hl7v2StoreGetIamPolicy { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2StoreGetIamPolicy(String hl7v2StoreName) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Hl7V2Stores.GetIamPolicy request = + client.projects().locations().datasets().hl7V2Stores().getIamPolicy(hl7v2StoreName); + + // Execute the request and process the results. + Policy policy = request.execute(); + System.out.println("HL7v2 store IAMPolicy retrieved: \n" + policy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_hl7v2_store_get_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreList.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreList.java new file mode 100644 index 00000000000..2a5bdbe1444 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreList.java @@ -0,0 +1,100 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_list_hl7v2_stores] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Hl7V2Store; +import com.google.api.services.healthcare.v1beta1.model.ListHl7V2StoresResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Hl7v2StoreList { + private static final String DATASET_NAME = "projects/%s/locations/%s/datasets/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2StoreList(String datasetName) throws IOException { + // String datasetName = + // String.format(DATASET_NAME, "your-project-id", "your-region-id", "your-dataset-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Results are paginated, so multiple queries may be required. + String pageToken = null; + List stores = new ArrayList<>(); + do { + // Create request and configure any parameters. + Hl7V2Stores.List request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .list(datasetName) + .setPageSize(100) // Specify pageSize up to 1000 + .setPageToken(pageToken); + + // Execute response and collect results. + ListHl7V2StoresResponse response = request.execute(); + stores.addAll(response.getHl7V2Stores()); + + // Update the page token for the next request. + pageToken = response.getNextPageToken(); + } while (pageToken != null); + + // Print results. + System.out.printf("Retrieved %s HL7v2 stores: \n", stores.size()); + for (Hl7V2Store data : stores) { + System.out.println("\t" + data.toPrettyString()); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_list_hl7v2_stores] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StorePatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StorePatch.java new file mode 100644 index 00000000000..e78c20698e0 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StorePatch.java @@ -0,0 +1,94 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_patch_hl7v2_store] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Hl7V2Store; +import com.google.api.services.healthcare.v1beta1.model.NotificationConfig; +import java.io.IOException; +import java.util.Collections; + +public class Hl7v2StorePatch { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void patchHl7v2Store(String hl7v2StoreName, String pubsubTopic) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + // String pubsubTopic = "your-pubsub-topic"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Fetch the initial state of the HL7v2 store. + Hl7V2Stores.Get getRequest = + client.projects().locations().datasets().hl7V2Stores().get(hl7v2StoreName); + Hl7V2Store store = getRequest.execute(); + + // Update the Hl7v2Store fields as needed as needed. For a full list of Hl7v2Store fields, see: + // https://cloud.google.com/healthcare/docs/reference/rest/v1beta1/projects.locations.datasets.hl7V2Store#Hl7v2Store + store.setNotificationConfig(new NotificationConfig().setPubsubTopic(pubsubTopic)); + + // Create request and configure any parameters. + Hl7V2Stores.Patch request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .patch(hl7v2StoreName, store) + .setUpdateMask("notificationConfig"); + + // Execute the request and process the results. + store = request.execute(); + System.out.println("HL7v2 store patched: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_patch_hl7v2_store] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreSetIamPolicy.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreSetIamPolicy.java new file mode 100644 index 00000000000..f39ea2accb5 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreSetIamPolicy.java @@ -0,0 +1,96 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2; + +// [START healthcare_hl7v2_store_set_iam_policy] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Binding; +import com.google.api.services.healthcare.v1beta1.model.Policy; +import com.google.api.services.healthcare.v1beta1.model.SetIamPolicyRequest; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; + +public class Hl7v2StoreSetIamPolicy { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2StoreSetIamPolicy(String hl7v2StoreName) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Configure the IAMPolicy to apply to the store. + // For more information on understanding IAM roles, see the following: + // https://cloud.google.com/iam/docs/understanding-roles + Binding binding = + new Binding() + .setRole("roles/healthcare.hl7V2Consumer") + .setMembers(Arrays.asList("domain:google.com")); + Policy policy = new Policy().setBindings(Arrays.asList(binding)); + SetIamPolicyRequest policyRequest = new SetIamPolicyRequest().setPolicy(policy); + + // Create request and configure any parameters. + Hl7V2Stores.SetIamPolicy request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .setIamPolicy(hl7v2StoreName, policyRequest); + + // Execute the request and process the results. + Policy updatedPolicy = request.execute(); + System.out.println("HL7v2 policy has been updated: " + updatedPolicy.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_hl7v2_store_set_iam_policy] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageCreate.java new file mode 100644 index 00000000000..ba422fe82c1 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageCreate.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_create_hl7v2_message] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.CreateMessageRequest; +import com.google.api.services.healthcare.v1beta1.model.Message; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +public class HL7v2MessageCreate { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessageCreate(String hl7v2StoreName, String messageId, String filePath) + throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + // String messageId = "your-message-id"; + // String filePath = "path/to/file.txt"; + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Load the data from file representing the message. + List lines = Files.readAllLines(Paths.get(filePath), Charset.defaultCharset()); + String data = String.join("\n", lines); + Message message = new Message().setData(data).setName(messageId); + CreateMessageRequest createRequest = new CreateMessageRequest().setMessage(message); + + // Create request and configure any parameters. + Messages.Create request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .messages() + .create(hl7v2StoreName, createRequest); + + // Execute the request and process the results. + Message response = request.execute(); + System.out.println("HL7v2 message created: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_create_hl7v2_message] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageDelete.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageDelete.java new file mode 100644 index 00000000000..36f4918b775 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageDelete.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_delete_hl7v2_message] + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import java.io.IOException; +import java.util.Collections; + +public class HL7v2MessageDelete { + private static final String MESSAGE_NAME = + "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s/messages/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessageDelete(String hl7v2MessageName) throws IOException { + // String hl7v2MessageName = + // String.format( + // MESSAGE_NAME, "project-id", "region-id", "dataset-id", "hl7v2-id", "message-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Messages.Delete request = + client.projects().locations().datasets().hl7V2Stores().messages().delete(hl7v2MessageName); + + // Execute the request and process the results. + request.execute(); + System.out.println("HL7v2 message deleted."); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_delete_hl7v2_message] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageGet.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageGet.java new file mode 100644 index 00000000000..6a559087bc5 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageGet.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_get_hl7v2_message] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Message; +import java.io.IOException; +import java.util.Collections; + +public class HL7v2MessageGet { + private static final String MESSAGE_NAME = + "projects/%s/locations/%s/datasets/%s/hl7C2Store/%s/messages/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessageGet(String hl7v2MessageName) throws IOException { + // String hl7v2MessageName = + // String.format( + // MESSAGE_NAME, "project-id", "region-id", "dataset-id", "hl7v2-id", "message-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Create request and configure any parameters. + Messages.Get request = + client.projects().locations().datasets().hl7V2Stores().messages().get(hl7v2MessageName); + + // Execute the request and process the results. + Message store = request.execute(); + System.out.println("HL7v2 message retrieved: \n" + store.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_get_hl7v2_message] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageIngest.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageIngest.java new file mode 100644 index 00000000000..32ba97c413b --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageIngest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_ingest_hl7v2_message] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.IngestMessageRequest; +import com.google.api.services.healthcare.v1beta1.model.IngestMessageResponse; +import com.google.api.services.healthcare.v1beta1.model.Message; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +public class HL7v2MessageIngest { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s"; + private static final String MESSAGE_NAME = + "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s/messages/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessageIngest(String hl7v2StoreName, String filePath) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Load the data from file and format it into an ingest request. + List lines = Files.readAllLines(Paths.get(filePath), Charset.defaultCharset()); + String data = String.join("\n", lines); + Message message = new Message().setData(data); + IngestMessageRequest ingestRequest = new IngestMessageRequest().setMessage(message); + + // Create request and configure any parameters. + Messages.Ingest request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .messages() + .ingest(hl7v2StoreName, ingestRequest); + + // Execute the request and process the results. + IngestMessageResponse response = request.execute(); + System.out.println("HL7v2 message ingested: " + response.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_ingest_hl7v2_message] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageList.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageList.java new file mode 100644 index 00000000000..45641c7e6b2 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageList.java @@ -0,0 +1,102 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_list_hl7v2_messages] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.ListMessagesResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class HL7v2MessageList { + private static final String HL7v2_NAME = "projects/%s/locations/%s/datasets/%s/hl7C2Store/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessageList(String hl7v2StoreName) throws IOException { + // String hl7v2StoreName = + // String.format( + // HL7v2_NAME, "your-project-id", "your-region-id", "your-dataset-id", "your-hl7v2-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Results are paginated, so multiple queries may be required. + String pageToken = null; + List messages = new ArrayList<>(); + + do { + // Create request and configure any parameters. + Messages.List request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .messages() + .list(hl7v2StoreName) + .setPageSize(100) // Specify pageSize up to 1000 + .setPageToken(pageToken); + + // Execute response and collect results. + ListMessagesResponse response = request.execute(); + messages.addAll(response.getMessages()); + + // Update the page token for the next request. + pageToken = response.getNextPageToken(); + } while (pageToken != null); + + // Print results. + System.out.printf("Retrieved %s HL7v2 stores: \n", messages.size()); + for (String data : messages) { + System.out.println("\t" + data); + } + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_list_hl7v2_messages] diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessagePatch.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessagePatch.java new file mode 100644 index 00000000000..3f53749f285 --- /dev/null +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessagePatch.java @@ -0,0 +1,99 @@ +/* + * Copyright 2019 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 snippets.healthcare.hl7v2.messages; + +// [START healthcare_patch_hl7v2_message] +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare.Projects.Locations.Datasets.Hl7V2Stores.Messages; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.Message; +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class HL7v2MessagePatch { + private static final String MESSAGE_NAME = + "projects/%s/locations/%s/datasets/%s/hl7V2Stores/%s/messages/%s"; + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + + public static void hl7v2MessagePatch(String hl7v2MessageName) throws IOException { + // String hl7v2MessageName = + // String.format( + // MESSAGE_NAME, "project-id", "region-id", "dataset-id", "hl7v2-id", "message-id"); + + // Initialize the client, which will be used to interact with the service. + CloudHealthcare client = createClient(); + + // Fetch the initial state of the message. + Messages.Get getRequest = + client.projects().locations().datasets().hl7V2Stores().messages().get(hl7v2MessageName); + Message message = getRequest.execute(); + + // Update the Message fields as needed as needed. For a full list of Message fields, see: + // https://cloud.google.com/healthcare/docs/reference/rest/v1beta1/projects.locations.datasets.hl7V2Stores.messages + Map labels = new HashMap<>(); + labels.put("key1", "value1"); + labels.put("key2", "value2"); + message.setLabels(labels); + + // Create request and configure any parameters. + Messages.Patch request = + client + .projects() + .locations() + .datasets() + .hl7V2Stores() + .messages() + .patch(hl7v2MessageName, message) + .setUpdateMask("labels"); + + // Execute the request and process the results. + message = request.execute(); + System.out.println("HL7v2 message patched: \n" + message.toPrettyString()); + } + + private static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } +} +// [END healthcare_patch_hl7v2_message] diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/DatasetTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/DatasetTests.java new file mode 100644 index 00000000000..38354e9d9b9 --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/DatasetTests.java @@ -0,0 +1,149 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.datasets.DatasetDeIdentify; +import snippets.healthcare.datasets.DatasetDelete; +import snippets.healthcare.datasets.DatasetGet; +import snippets.healthcare.datasets.DatasetGetIamPolicy; +import snippets.healthcare.datasets.DatasetList; +import snippets.healthcare.datasets.DatasetPatch; +import snippets.healthcare.datasets.DatasetSetIamPolicy; + +@RunWith(JUnit4.class) +public class DatasetTests { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static String datasetName; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void beforeTest() throws IOException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + datasetName = + String.format("projects/%s/locations/%s/datasets/%s", PROJECT_ID, REGION_ID, datasetId); + + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_DatasetCreate() throws IOException { + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, "new-dataset"); + + String output = bout.toString(); + assertThat(output, containsString("Dataset created.")); + } + + @Test + public void test_DatasetGet() throws IOException { + DatasetGet.datasetGet(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Dataset retrieved:")); + } + + @Test + public void test_DatasetList() throws IOException { + DatasetList.datasetList(PROJECT_ID, REGION_ID); + + String output = bout.toString(); + assertThat(output, containsString("Retrieved")); + } + + @Test + public void test_DataSetPatch() throws IOException { + DatasetPatch.datasetPatch(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Dataset patched:")); + } + + @Test + public void test_DatasetDeidentify() throws IOException { + DatasetDeIdentify.datasetDeIdentify(datasetName, datasetName + "-died"); + + String output = bout.toString(); + assertThat(output, containsString("De-identified Dataset created.")); + } + + @Test + public void test_DatasetGetIamPolicy() throws IOException { + DatasetGetIamPolicy.datasetGetIamPolicy(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Dataset IAMPolicy retrieved:")); + } + + @Test + public void test_DatasetSetIamPolicy() throws IOException { + DatasetSetIamPolicy.datasetSetIamPolicy(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Dataset policy has been updated: ")); + } + + @Test + public void test_DatasetDelete() throws IOException { + DatasetDelete.datasetDelete(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Dataset deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreStudyTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreStudyTests.java new file mode 100644 index 00000000000..f4d4d5f6366 --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreStudyTests.java @@ -0,0 +1,140 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URISyntaxException; +import java.util.UUID; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.dicom.DicomStoreCreate; +import snippets.healthcare.dicom.DicomWebDeleteStudy; +import snippets.healthcare.dicom.DicomWebRetrieveStudy; +import snippets.healthcare.dicom.DicomWebSearchForInstances; +import snippets.healthcare.dicom.DicomWebStoreInstance; + +@RunWith(JUnit4.class) +public class DicomStoreStudyTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static String dicomStoreName; + + // The studyUid is not assigned by the server and is part of the metadata of dcmFile. + private static String studyId = "2.25.330012077234033941963257891139480825153"; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + String datasetName = String.format( + "projects/%s/locations/%s/datasets/%s", + PROJECT_ID, + REGION_ID, + datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + + String dicomStoreId = "dicom-" + UUID.randomUUID().toString().replaceAll("-", "_"); + dicomStoreName = String.format("%s/dicomStores/%s", datasetName, dicomStoreId); + + DicomStoreCreate.dicomStoreCreate(datasetName, dicomStoreId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException, URISyntaxException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + // Store before each test so it is always available. + DicomWebStoreInstance.dicomWebStoreInstance( + dicomStoreName, "src/test/resources/jpeg_text.dcm"); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_DicomWebStoreInstance() throws Exception { + DicomWebStoreInstance.dicomWebStoreInstance( + dicomStoreName, "src/test/resources/jpeg_text.dcm"); + + String output = bout.toString(); + assertThat(output, containsString("DICOM instance stored:")); + } + + @Test + public void test_DicomWebSearchInstances() throws Exception { + DicomWebSearchForInstances.dicomWebSearchForInstances(dicomStoreName); + String output = bout.toString(); + assertThat(output, containsString("Dicom store instances found:")); + } + + @Test + public void test_DicomWebRetrieveStudy() throws Exception { + DicomWebRetrieveStudy.dicomWebRetrieveStudy(dicomStoreName, studyId); + + String output = bout.toString(); + assertThat(output, containsString("DICOM study retrieved:")); + assertThat(output, containsString(studyId)); + } + + @Test + public void test_DicomWebDeleteStudy() throws IOException { + DicomWebDeleteStudy.dicomWebDeleteStudy(dicomStoreName, studyId); + + String output = bout.toString(); + assertThat(output, containsString("DICOM study deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreTests.java new file mode 100644 index 00000000000..26b0870576a --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreTests.java @@ -0,0 +1,181 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.dicom.DicomStoreCreate; +import snippets.healthcare.dicom.DicomStoreDelete; +import snippets.healthcare.dicom.DicomStoreExport; +import snippets.healthcare.dicom.DicomStoreGet; +import snippets.healthcare.dicom.DicomStoreGetIamPolicy; +import snippets.healthcare.dicom.DicomStoreImport; +import snippets.healthcare.dicom.DicomStoreList; +import snippets.healthcare.dicom.DicomStorePatch; +import snippets.healthcare.dicom.DicomStoreSetIamPolicy; + +@RunWith(JUnit4.class) +public class DicomStoreTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static final String GCLOUD_BUCKET_NAME = "java-docs-samples-testing"; + private static final String GCLOUD_PUBSUB_TOPIC = System.getenv("GCLOUD_PUBSUB_TOPIC"); + + private static String datasetName; + + private static String dicomStoreName; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + requireEnvVar("GCLOUD_PUBSUB_TOPIC"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + datasetName = + String.format("projects/%s/locations/%s/datasets/%s", PROJECT_ID, REGION_ID, datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + String dicomStoreId = "dicom-" + UUID.randomUUID().toString().replaceAll("-", "_"); + dicomStoreName = String.format("%s/dicomStores/%s", datasetName, dicomStoreId); + + DicomStoreCreate.dicomStoreCreate(datasetName, dicomStoreId); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_DicomStoreCreate() throws IOException { + DicomStoreCreate.dicomStoreCreate(datasetName, "new-dicom-store"); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store created:")); + } + + @Test + public void test_DicomStoreGet() throws IOException { + DicomStoreGet.dicomeStoreGet(dicomStoreName); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store retrieved:")); + } + + @Test + public void test_DicomStoreGetIamPolicy() throws IOException { + DicomStoreGetIamPolicy.dicomStoreGetIamPolicy(dicomStoreName); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store IAMPolicy retrieved:")); + } + + @Test + public void test_DicomStoreSetIamPolicy() throws IOException { + DicomStoreSetIamPolicy.dicomStoreSetIamPolicy(dicomStoreName); + + String output = bout.toString(); + assertThat(output, containsString("DICOM policy has been updated: ")); + } + + @Test + public void test_DicomStoreList() throws IOException { + DicomStoreList.dicomStoreList(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Retrieved")); + } + + @Test + public void test_DicomStorePatch() throws IOException { + DicomStorePatch.patchDicomStore(dicomStoreName, GCLOUD_PUBSUB_TOPIC); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store patched: ")); + } + + @Test + public void test_DicomStoreExport() throws IOException { + String gcsPath = String.format("gs://%s", GCLOUD_BUCKET_NAME); + DicomStoreExport.dicomStoreExport(dicomStoreName, gcsPath); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store export complete.")); + } + + @Test + public void test_DicomStoreImport() throws IOException { + String gcsPath = + String.format("gs://%s/%s", GCLOUD_BUCKET_NAME, "IM-0002-0001-JPEG-BASELINE.dcm"); + DicomStoreImport.dicomStoreImport(dicomStoreName, gcsPath); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store import complete.")); + } + + @Test + public void test_DicomStoreDelete() throws IOException { + DicomStoreDelete.deleteDicomStore(dicomStoreName); + + String output = bout.toString(); + assertThat(output, containsString("DICOM store deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirResourceTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirResourceTests.java new file mode 100644 index 00000000000..6eef0135935 --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirResourceTests.java @@ -0,0 +1,247 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URISyntaxException; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.fhir.FhirStoreCreate; +import snippets.healthcare.fhir.resources.FhirResourceConditionalPatch; +import snippets.healthcare.fhir.resources.FhirResourceConditionalUpdate; +import snippets.healthcare.fhir.resources.FhirResourceCreate; +import snippets.healthcare.fhir.resources.FhirResourceDelete; +import snippets.healthcare.fhir.resources.FhirResourceDeletePurge; +import snippets.healthcare.fhir.resources.FhirResourceGet; +import snippets.healthcare.fhir.resources.FhirResourceGetHistory; +import snippets.healthcare.fhir.resources.FhirResourceGetMetadata; +import snippets.healthcare.fhir.resources.FhirResourceGetPatientEverything; +import snippets.healthcare.fhir.resources.FhirResourcePatch; +import snippets.healthcare.fhir.resources.FhirResourceSearch; +import snippets.healthcare.fhir.resources.FhirResourceSearchPost; + +@RunWith(JUnit4.class) +public class FhirResourceTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static String fhirStoreName; + + private String fhirResourceId; + private String fhirResourceName; + + private static String patientType = "Patient"; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable \"%s\" is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + String datasetName = String.format( + "projects/%s/locations/%s/datasets/%s", + PROJECT_ID, + REGION_ID, + datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + + String fhirStoreId = "fhir-" + UUID.randomUUID().toString().replaceAll("-", "_"); + fhirStoreName = String.format("%s/fhirStores/%s", datasetName, fhirStoreId); + FhirStoreCreate.fhirStoreCreate(datasetName, fhirStoreId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException, URISyntaxException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + FhirResourceCreate.fhirResourceCreate(fhirStoreName, patientType); + + Matcher idMatcher = Pattern.compile("\"id\": \"([^\"]*)\",").matcher(bout.toString()); + if (idMatcher.find()) { + fhirResourceId = idMatcher.group(1); + fhirResourceName = String.format("%s/fhir/%s/%s", fhirStoreName, patientType, fhirResourceId); + } + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + + @Test + public void test_FhirResourceCreate() throws Exception { + FhirResourceCreate.fhirResourceCreate(fhirStoreName, patientType); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource created:")); + } + + @Test + public void test_FhirResourceSearch() throws Exception { + FhirResourceSearch.fhirResourceSearch(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource search results:")); + } + + @Test + public void test_FhirResourceSearchPost() throws Exception { + FhirResourceSearchPost.fhirResourceSearchPost(fhirStoreName, patientType); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource search results:")); + } + + @Test + public void test_FhirResourceGet() throws Exception { + FhirResourceGet.fhirResourceGet(fhirResourceName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource retrieved:")); + } + + @Test + public void test_FhirResourcePatch() throws Exception { + FhirResourcePatch.fhirResourcePatch( + fhirResourceName, + "[{\"op\": \"add\", \"path\": \"/active\", \"value\": false}]"); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource patched:")); + } + + @Test + public void test_FhirResourceConditionalPatch() throws Exception { + FhirResourceConditionalPatch.fhirResourceConditionalPatch( + fhirStoreName, + patientType, + fhirResourceId, + "[{\"op\": \"add\", \"path\": \"/active\", \"value\": true}]"); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource conditionally patched:")); + } + + @Test + public void test_FhirResourceConditionalUpdate() throws Exception { + FhirResourceConditionalUpdate.fhirResourceConditionalUpdate( + fhirStoreName, + patientType, + String.format( + "{\"resourceType\": \"%s\", \"active\": true, \"id\": \"%s\"}", + patientType, + fhirResourceId)); + + String output = bout.toString(); + assertThat(output, containsString(String.format("FHIR resource conditionally replaced:"))); + } + + @Test + public void test_FhirResourceGetPatientEverything() throws Exception { + FhirResourceGetPatientEverything.fhirResourceGetPatientEverything(fhirResourceName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource search results:")); + } + + @Test + public void test_GetFhirResourceMetadata() throws Exception { + FhirResourceGetMetadata.fhirResourceGetMetadata(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource metadata retrieved:")); + } + + @Test + public void test_FhirResourceDelete() throws Exception { + FhirResourceDelete.fhirResourceDelete(fhirResourceName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource deleted.")); + + bout.reset(); + try { + FhirResourceGet.fhirResourceGet(fhirResourceName); + fail(); + } catch (RuntimeException ex) { + assertThat(ex.getMessage(), containsString("404")); + } + } + + @Test + public void test_FhirResourceGetHistory() throws Exception { + FhirResourcePatch.fhirResourcePatch( + fhirResourceName, + "[{\"op\": \"add\", \"path\": \"/active\", \"value\": false}]"); + FhirResourceGetHistory.fhirResourceGetHistory(fhirResourceName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource history retrieved:")); + } + + @Test + public void test_DeletePurgeFhirResource() throws Exception { + FhirResourcePatch.fhirResourcePatch( + fhirResourceName, + "[{\"op\": \"add\", \"path\": \"/active\", \"value\": false}]"); + FhirResourceDelete.fhirResourceDelete(fhirResourceName); + FhirResourceDeletePurge.fhirResourceDeletePurge(fhirResourceName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR resource purged.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirStoreTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirStoreTests.java new file mode 100644 index 00000000000..d1ba39f24a0 --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/FhirStoreTests.java @@ -0,0 +1,192 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.fhir.FhirStoreCreate; +import snippets.healthcare.fhir.FhirStoreDelete; +import snippets.healthcare.fhir.FhirStoreExecuteBundle; +import snippets.healthcare.fhir.FhirStoreExport; +import snippets.healthcare.fhir.FhirStoreGet; +import snippets.healthcare.fhir.FhirStoreGetIamPolicy; +import snippets.healthcare.fhir.FhirStoreImport; +import snippets.healthcare.fhir.FhirStoreList; +import snippets.healthcare.fhir.FhirStorePatch; +import snippets.healthcare.fhir.FhirStoreSetIamPolicy; + +@RunWith(JUnit4.class) +public class FhirStoreTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static final String GCLOUD_BUCKET_NAME = "java-docs-samples-testing"; + private static final String GCLOUD_PUBSUB_TOPIC = System.getenv("GCLOUD_PUBSUB_TOPIC"); + + private static String storageFileName = "IM-0002-0001-JPEG-BASELINE.dcm"; + private static String gcsFileName = GCLOUD_BUCKET_NAME + "/" + storageFileName; + + private static String datasetName; + + private static String fhirStoreName; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + requireEnvVar("GCLOUD_PUBSUB_TOPIC"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + datasetName = + String.format("projects/%s/locations/%s/datasets/%s", PROJECT_ID, REGION_ID, datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + String fhirStoreId = "fhir-" + UUID.randomUUID().toString().replaceAll("-", "_"); + fhirStoreName = String.format("%s/fhirStores/%s", datasetName, fhirStoreId); + + FhirStoreCreate.fhirStoreCreate(datasetName, fhirStoreId); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_FhirStoreCreate() throws IOException { + FhirStoreCreate.fhirStoreCreate(datasetName, "new-fhir-store"); + + String output = bout.toString(); + assertThat(output, containsString("FHIR store created: ")); + } + + @Test + public void test_FhirStoreGet() throws Exception { + FhirStoreGet.fhirStoreGet(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR store retrieved:")); + } + + @Test + public void test_FhirStoreGetIamPolicy() throws Exception { + FhirStoreGetIamPolicy.fhirStoreGetIamPolicy(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR store IAMPolicy retrieved:")); + } + + @Test + public void test_FhirStoreSetIamPolicy() throws Exception { + FhirStoreSetIamPolicy.fhirStoreSetIamPolicy(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR policy has been updated:")); + } + + @Test + public void test_FhirStoreList() throws Exception { + FhirStoreList.fhirStoreList(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Retrieved ")); + } + + @Test + public void test_FhirStorePatch() throws Exception { + FhirStorePatch.fhirStorePatch(fhirStoreName, GCLOUD_PUBSUB_TOPIC); + + String output = bout.toString(); + assertThat(output, containsString("Fhir store patched:")); + } + + @Test + public void test_ExecuteFhirBundle() throws Exception { + FhirStoreExecuteBundle.fhirStoreExecuteBundle( + fhirStoreName, + "{\"resourceType\": \"Bundle\",\"type\": \"batch\",\"entry\": []}"); + + String output = bout.toString(); + assertThat(output, containsString("FHIR bundle executed:")); + } + + @Test + public void test_FhirStoreExport() throws Exception { + FhirStoreExport.fhirStoreExport(fhirStoreName, "gs://" + GCLOUD_BUCKET_NAME); + + String output = bout.toString(); + assertThat(output, containsString("Fhir store export complete.")); + } + + @Test + public void test_FhirStoreImport() throws Exception { + FhirStoreImport.fhirStoreImport(fhirStoreName, "gs://" + gcsFileName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR store import complete:")); + } + + @Test + public void test_FhirStoreDelete() throws Exception { + FhirStoreDelete.fhirStoreDelete(fhirStoreName); + + String output = bout.toString(); + assertThat(output, containsString("FHIR store deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2MessageTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2MessageTests.java new file mode 100644 index 00000000000..60f2b387a2d --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2MessageTests.java @@ -0,0 +1,169 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.hl7v2.Hl7v2StoreCreate; +import snippets.healthcare.hl7v2.messages.HL7v2MessageCreate; +import snippets.healthcare.hl7v2.messages.HL7v2MessageDelete; +import snippets.healthcare.hl7v2.messages.HL7v2MessageGet; +import snippets.healthcare.hl7v2.messages.HL7v2MessageIngest; +import snippets.healthcare.hl7v2.messages.HL7v2MessageList; +import snippets.healthcare.hl7v2.messages.HL7v2MessagePatch; + +@RunWith(JUnit4.class) +public class Hl7v2MessageTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static String datasetName; + + private static String hl7v2StoreName; + + private static String messageName; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + datasetName = + String.format("projects/%s/locations/%s/datasets/%s", PROJECT_ID, REGION_ID, datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + String hl7v2StoreId = "hl7v2-" + UUID.randomUUID().toString().replaceAll("-", "_"); + hl7v2StoreName = String.format("%s/hl7V2Stores/%s", datasetName, hl7v2StoreId); + Hl7v2StoreCreate.hl7v2StoreCreate(datasetName, hl7v2StoreId); + + String messageId = "message-" + UUID.randomUUID().toString().replaceAll("-", "_"); + + String hl7v2MessagePrefix = hl7v2StoreName + "/messages"; + + HL7v2MessageCreate.hl7v2MessageCreate( + hl7v2StoreName, messageId, "src/test/resources/hl7v2-sample-ingest.txt"); + + Pattern messageNamePattern = + Pattern.compile(String.format("\"(?%s/[^/\"]+)\"", hl7v2MessagePrefix)); + Matcher messageNameMatcher = messageNamePattern.matcher(bout.toString()); + assertTrue(messageNameMatcher.find()); + // '=' is encoded for JSON, but won't work for 'get'. + messageName = messageNameMatcher.group("messageName").replace("\\u003d", "="); + messageId = messageName.substring(messageName.indexOf("messages/") + "messages/".length()); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_HL7v2MessageCreate() throws Exception { + HL7v2MessageCreate.hl7v2MessageCreate( + hl7v2StoreName, "new-hl7v2-message", "src/test/resources/hl7v2-sample-ingest.txt"); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 message created: ")); + } + + @Test + public void test_GetHL7v2Message() throws Exception { + HL7v2MessageGet.hl7v2MessageGet(messageName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 message retrieved:")); + } + + @Test + public void test_Hl7v2MessageList() throws Exception { + HL7v2MessageList.hl7v2MessageList(hl7v2StoreName); + + String output = bout.toString(); + assertThat(output, containsString("Retrieved ")); + } + + @Test + public void test_Hl7v2MessagePatch() throws Exception { + HL7v2MessagePatch.hl7v2MessagePatch(messageName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 message patched:")); + } + + @Test + public void test_Hl7v2MessageIngest() throws Exception { + HL7v2MessageIngest.hl7v2MessageIngest( + hl7v2StoreName, "src/test/resources/hl7v2-sample-ingest.txt"); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 message ingested:")); + } + + @Test + public void test_DeleteHL7v2Message() throws Exception { + HL7v2MessageDelete.hl7v2MessageDelete(messageName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 message deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2StoreTests.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2StoreTests.java new file mode 100644 index 00000000000..2e07b772f5b --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2StoreTests.java @@ -0,0 +1,146 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import snippets.healthcare.datasets.DatasetCreate; +import snippets.healthcare.hl7v2.Hl7v2StoreCreate; +import snippets.healthcare.hl7v2.Hl7v2StoreDelete; +import snippets.healthcare.hl7v2.Hl7v2StoreGet; +import snippets.healthcare.hl7v2.Hl7v2StoreGetIamPolicy; +import snippets.healthcare.hl7v2.Hl7v2StoreList; +import snippets.healthcare.hl7v2.Hl7v2StoreSetIamPolicy; + +@RunWith(JUnit4.class) +public class Hl7v2StoreTests extends TestBase { + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + private static String datasetName; + + private static String hl7v2StoreName; + + private final PrintStream originalOut = System.out; + private ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + String.format("Environment variable '%s' is required to perform these tests.", varName)); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @BeforeClass + public static void setUp() throws IOException { + String datasetId = "dataset-" + UUID.randomUUID().toString().replaceAll("-", "_"); + datasetName = + String.format("projects/%s/locations/%s/datasets/%s", PROJECT_ID, REGION_ID, datasetId); + DatasetCreate.datasetCreate(PROJECT_ID, REGION_ID, datasetId); + } + + @AfterClass + public static void deleteTempItems() throws IOException { + deleteDatasets(); + } + + @Before + public void beforeTest() throws IOException { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + + String hl7v2StoreId = "hl7v2-" + UUID.randomUUID().toString().replaceAll("-", "_"); + hl7v2StoreName = String.format("%s/hl7V2Stores/%s", datasetName, hl7v2StoreId); + Hl7v2StoreCreate.hl7v2StoreCreate(datasetName, hl7v2StoreId); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(originalOut); + bout.reset(); + } + + @Test + public void test_Hl7v2StoreCreate() throws Exception { + Hl7v2StoreCreate.hl7v2StoreCreate(datasetName, "new-hlv2store"); + + String output = bout.toString(); + assertThat(output, containsString("Hl7V2Store store created:")); + } + + @Test + public void test_Hl7v2StoreGet() throws Exception { + Hl7v2StoreGet.hl7v2eStoreGet(hl7v2StoreName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 store retrieved:")); + } + + @Test + public void test_Hl7v2StoreGetIamPolicy() throws Exception { + Hl7v2StoreGetIamPolicy.hl7v2StoreGetIamPolicy(hl7v2StoreName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 store IAMPolicy retrieved:")); + } + + @Test + public void test_Hl7v2StoreSetIamPolicy() throws Exception { + Hl7v2StoreSetIamPolicy.hl7v2StoreSetIamPolicy(hl7v2StoreName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 policy has been updated:")); + } + + @Test + public void test_Hl7v2StoreList() throws Exception { + Hl7v2StoreList.hl7v2StoreList(datasetName); + + String output = bout.toString(); + assertThat(output, containsString("Retrieved")); + } + + @Test + public void test_Hl7v2StoreDelete() throws Exception { + Hl7v2StoreDelete.hl7v2StoreDelete(hl7v2StoreName); + + String output = bout.toString(); + assertThat(output, containsString("HL7v2 store deleted.")); + } +} diff --git a/healthcare/v1beta1/src/test/java/snippets/healthcare/TestBase.java b/healthcare/v1beta1/src/test/java/snippets/healthcare/TestBase.java new file mode 100644 index 00000000000..3e4117b7add --- /dev/null +++ b/healthcare/v1beta1/src/test/java/snippets/healthcare/TestBase.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 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 snippets.healthcare; + +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.http.HttpHeaders; +import com.google.api.client.http.HttpRequestInitializer; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.healthcare.v1beta1.CloudHealthcare; +import com.google.api.services.healthcare.v1beta1.CloudHealthcareScopes; +import com.google.api.services.healthcare.v1beta1.model.ListDatasetsResponse; + +import java.io.IOException; +import java.util.Collections; + +public class TestBase { + private static final JsonFactory JSON_FACTORY = new JacksonFactory(); + private static final NetHttpTransport HTTP_TRANSPORT = new NetHttpTransport(); + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static final String REGION_ID = "us-central1"; + + protected static CloudHealthcare createClient() throws IOException { + // Use Application Default Credentials (ADC) to authenticate the requests + // For more information see https://cloud.google.com/docs/authentication/production + GoogleCredential credential = + GoogleCredential.getApplicationDefault(HTTP_TRANSPORT, JSON_FACTORY) + .createScoped(Collections.singleton(CloudHealthcareScopes.CLOUD_PLATFORM)); + + // Create a HttpRequestInitializer, which will provide a baseline configuration to all requests. + HttpRequestInitializer requestInitializer = + request -> { + credential.initialize(request); + request.setHeaders(new HttpHeaders().set("X-GFE-SSL", "yes")); + request.setConnectTimeout(60000); // 1 minute connect timeout + request.setReadTimeout(60000); // 1 minute read timeout + }; + + // Build the client for interacting with the service. + return new CloudHealthcare.Builder(HTTP_TRANSPORT, JSON_FACTORY, requestInitializer) + .setApplicationName("your-application-name") + .build(); + } + + protected static void deleteDatasets() throws IOException { + CloudHealthcare client = createClient(); + + String parentName = String.format( + "projects/%s/locations/%s", + PROJECT_ID, + REGION_ID); + ListDatasetsResponse response = client + .projects() + .locations() + .datasets() + .list(parentName) + .execute(); + if (response.getDatasets() == null) { + return; + } + for (int i = 0; i < response.getDatasets().size(); i++) { + client + .projects() + .locations() + .datasets() + .delete(response.getDatasets().get(i).getName()) + .execute(); + } + } + +} diff --git a/healthcare/v1beta1/src/test/resources/hl7v2-sample-ingest.txt b/healthcare/v1beta1/src/test/resources/hl7v2-sample-ingest.txt new file mode 100644 index 00000000000..f78b1a5aa53 --- /dev/null +++ b/healthcare/v1beta1/src/test/resources/hl7v2-sample-ingest.txt @@ -0,0 +1 @@ +TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZfEF8QXwyMDE4MDEwMTAwMDAwMHx8VFlQRV5BfDIwMTgwMTAxMDAwMDAwfFR8MC4wfHx8QUF8fDAwfEFTQ0lJDUVWTnxBMDB8MjAxODAxMDEwMDAwMDANUElEfHwxMTExMTFeXl5eTVJOfDExMTExMTExXl5eXk1STn4xMTExMTExMTExXl5eXk5IU05NQlINCg== \ No newline at end of file diff --git a/healthcare/v1beta1/src/test/resources/jpeg_text.dcm b/healthcare/v1beta1/src/test/resources/jpeg_text.dcm new file mode 100644 index 00000000000..950fb16166c Binary files /dev/null and b/healthcare/v1beta1/src/test/resources/jpeg_text.dcm differ diff --git a/iam/api-client/pom.xml b/iam/api-client/pom.xml index 153e85b48bd..a4dc25e7846 100644 --- a/iam/api-client/pom.xml +++ b/iam/api-client/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/iap/pom.xml b/iap/pom.xml index 208d2f83ead..505025d34a7 100644 --- a/iap/pom.xml +++ b/iap/pom.xml @@ -29,7 +29,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/iot/api-client/beta-features/manager/README.md b/iot/api-client/beta-features/manager/README.md deleted file mode 100644 index 7fed80c4253..00000000000 --- a/iot/api-client/beta-features/manager/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Cloud IoT Core Java Gateway Command Sample - - -Open in Cloud Shell - -This sample app demonstrates sending telemetry data on behalf of a device using -a Gateway. - -Note that before you can run the sample, you must configure a Google Cloud -PubSub topic for Cloud IoT as described in [the parent README](../README.md). - -Before running the samples, you can set the `GOOGLE_CLOUD_PROJECT` and -`GOOGLE_APPLICATION_CREDENTIALS` environment variables to avoid passing them to -the sample every time you run it. - -## Setup -Run the following command to install the libraries and build the sample with -Maven: - - mvn clean compile assembly:single - -## Running the sample - -The following command will run the sample - - - mvn exec:java -Dexec.mainClass="com.example.cloud.iot.examples.DeviceGatewayExample" - -The following description summarizes the sample usage: - - usage: DeviceGatewayExample [--cloud_region ] --command - [--device_id ] [--project_id ] [--registry_name ] - [--telemetry_data ] - Cloud IoT Core Commandline Example (Device Gateways): - - --cloud_region GCP cloud region. - --command Command to run: - send-delegate-telemetry - --device_id Name for the delegate device. - --project_id GCP cloud project name. - --registry_name Name for your Device Registry. - --telemetry_data The telemetry data (string or JSON) to send - on behalf of the delegated device. - - https://cloud.google.com/iot-core - -The following example shows using the sample to send the telemetry data `hello` -on behalf of the device `some-device-id`: - - mvn exec:java -Dexec.mainClass="com.example.cloud.iot.examples.DeviceGatewayExample" \ - -Dexec.args="-cloud_region=us-central1 \ - -project_id=blue-jet-123 \ - -command=send-delegate-telemetry \ - -device_id=your-device-id \ - -telemetry_data=hello \ - -device_id=some-device-id \ - -registry_name=my-registry" - -## Troubleshooting -Make sure to bind your device before trying to attach it. If your device is not -bound to the gateway, the call to attach the device will not return. diff --git a/iot/api-client/beta-features/manager/pom.xml b/iot/api-client/beta-features/manager/pom.xml deleted file mode 100644 index 01474c20053..00000000000 --- a/iot/api-client/beta-features/manager/pom.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - 4.0.0 - com.example.cloud - cloudiot-manager-demo - jar - 1.0 - cloudiot-manager-demo - http://maven.apache.org - - - - com.google.cloud.samples - shared-configuration - 1.0.8 - - - - - 1.8 - 1.8 - - - - - org.eclipse.paho - org.eclipse.paho.client.mqttv3 - 1.2.0 - - - org.json - json - 20090211 - - - io.jsonwebtoken - jjwt - 0.7.0 - - - joda-time - joda-time - 2.1 - - - - com.google.apis - google-api-services-cloudiot - v1-rev20181120-1.27.0 - - - - com.google.cloud - google-cloud-pubsub - 0.24.0-beta - - - com.google.oauth-client - google-oauth-client - 1.23.0 - - - com.google.guava - guava - 23.0 - - - com.google.api-client - google-api-client - 1.23.0 - - - commons-cli - commons-cli - 1.3 - - - - - junit - junit - 4.12 - test - - - com.google.truth - truth - 0.34 - test - - - - - - - maven-assembly-plugin - - - - com.example.cloudiot.Manage - - - - jar-with-dependencies - - - - - - diff --git a/iot/api-client/beta-features/manager/resources/README.md b/iot/api-client/beta-features/manager/resources/README.md deleted file mode 100644 index 27fbefe8215..00000000000 --- a/iot/api-client/beta-features/manager/resources/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Test public certificate files - -The certificates in this folder are only provided for testing and should not be -used for registering your devices. Instructions and a shell script are in the -parent folder for getting started. diff --git a/iot/api-client/beta-features/manager/resources/ec_private.pem b/iot/api-client/beta-features/manager/resources/ec_private.pem deleted file mode 100644 index aea8e88143c..00000000000 --- a/iot/api-client/beta-features/manager/resources/ec_private.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN EC PRIVATE KEY----- -MHcCAQEEIK9PAsoXug32KzMJiah9Nuy9yNZJdpDYfIeUt3olsRZ9oAoGCCqGSM49 -AwEHoUQDQgAES+slfwEIqd6EqRy5sDtFJXzW+D+i5tDWD5EVFA0loXkisKpgEvww -fCx6xwSNatAevzpmFFqsvp6ouEop7RqRLw== ------END EC PRIVATE KEY----- diff --git a/iot/api-client/beta-features/manager/resources/ec_private_pkcs8 b/iot/api-client/beta-features/manager/resources/ec_private_pkcs8 deleted file mode 100644 index ef267dd2aaf..00000000000 Binary files a/iot/api-client/beta-features/manager/resources/ec_private_pkcs8 and /dev/null differ diff --git a/iot/api-client/beta-features/manager/resources/ec_public.pem b/iot/api-client/beta-features/manager/resources/ec_public.pem deleted file mode 100644 index 33f0ed35609..00000000000 --- a/iot/api-client/beta-features/manager/resources/ec_public.pem +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES+slfwEIqd6EqRy5sDtFJXzW+D+i -5tDWD5EVFA0loXkisKpgEvwwfCx6xwSNatAevzpmFFqsvp6ouEop7RqRLw== ------END PUBLIC KEY----- diff --git a/iot/api-client/beta-features/manager/resources/rsa_cert.pem b/iot/api-client/beta-features/manager/resources/rsa_cert.pem deleted file mode 100644 index 2d88549be70..00000000000 --- a/iot/api-client/beta-features/manager/resources/rsa_cert.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICnjCCAYYCCQDqmwKbBginQjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ1 -bnVzZWQwHhcNMTgxMTE0MjI0OTIxWhcNMTgxMjE0MjI0OTIxWjARMQ8wDQYDVQQD -DAZ1bnVzZWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkr+ZWUm0j -/dDc9rwzkWal8pq8iEZbYvaH1wavsrr0Rsmi0AF20NKg8dlBMZdwQ3bAZtJKVq8z -bhy9brXpgtGHSZpdqfGIUIH+OKJcGdWYIXFYJY/LTjrrLFex8QdYNenlVQCCcmEj -lxNmOjhTeTFN8v1AWy+nSbrHqGWY77yenF3vPE49ReOjJQwJmNQBBZB6BbI3RlYu -0d/zYJTBy64GhC46UdSqLh3UgNtvXIP+pqeTDVpVuVVX+42vEJsdbNAh0ZmGsh3f -f+HrG6Jaujl/j8jHXo0NrUYk9kpcQNDCbq2NLRfCauQY96kLeYtxg7nzpbsejCAy -pSzLrzpNwkybAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAC5g7YGMG29+JdvvQSdH -MmT0p3Jxtfzra7JAxVyM4AzIvK67FvDHHAOR4D4sEyyG/atAq5i3Efh09Ag1WsV6 -0Tqn65HbS0IwwI5NTicB5cdh/5EoxhvzNyy6wyw0S9It/2zcwJZuYm+uPVZRRbhE -9pi4xTRWUmdnFoZWd2iSA+EdPkDLRz+hvPXDR7JGsmilKp6vtRcu8h3RMPA6kuc/ -q7zU7qY3SWTYpnhR8QjkEPtVe9EiGnX8cTy4EORyZgQNd0sfMU/suDgdkirNx3jE -ZF+iBjRzvsZEyZOO9yEf6bX1v08G8X3EuIjTsb+XXxhV7MEklVoiOnS8Y2z1XeOQ -XiI= ------END CERTIFICATE----- diff --git a/iot/api-client/beta-features/manager/resources/rsa_private.pem b/iot/api-client/beta-features/manager/resources/rsa_private.pem deleted file mode 100644 index 6b89f84edb6..00000000000 --- a/iot/api-client/beta-features/manager/resources/rsa_private.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDkr+ZWUm0j/dDc -9rwzkWal8pq8iEZbYvaH1wavsrr0Rsmi0AF20NKg8dlBMZdwQ3bAZtJKVq8zbhy9 -brXpgtGHSZpdqfGIUIH+OKJcGdWYIXFYJY/LTjrrLFex8QdYNenlVQCCcmEjlxNm -OjhTeTFN8v1AWy+nSbrHqGWY77yenF3vPE49ReOjJQwJmNQBBZB6BbI3RlYu0d/z -YJTBy64GhC46UdSqLh3UgNtvXIP+pqeTDVpVuVVX+42vEJsdbNAh0ZmGsh3ff+Hr -G6Jaujl/j8jHXo0NrUYk9kpcQNDCbq2NLRfCauQY96kLeYtxg7nzpbsejCAypSzL -rzpNwkybAgMBAAECggEBAM/Wdba6TurJAQvxSnZrjSkA5lS2XYss0/X9HNyNyY+8 -zgCkntAHVYZkhxjTI1kqV0DhsflR8wUA7CnV9op1FEyqPhsmGpfS43HSsuyVpiQP -MN31tUwGm1GlCUZ1UkF/LkX5DO+BWHtqEH12KD7lBERdtIDK3vJg9doDV+K472oN -5sBT35aW6CUXrFRcu/MPTY0QSob06P4Isv8/9nWcjsx+20dM0xhEyEV7NMKR/hcU -+ckGMsF1zRtqof78oXztbrgiTGLljYi0IGC5ciC7EvQjiP9tMIK79sUcG3EHkZrQ -8S0Lf0cOGmYxBvffMEpm8UeCPTrUBZQ/L6M9W8F6XJECgYEA++CQduOway8NuFjc -79GfBWvQOmpxuJq7PVZo1kKcgYqJV7Wtlq3lmZ5/vLhMDLyKw6TMJ0s2a40Mepwo -ci9jFGLOYpp+/t80EkJqumsgbyYkxIb9KRrZ6TY+/lsKugGGzHdU1BAB6GsmWVo7 -9EPa0KapalHMrvAy7YgUdXMLw/cCgYEA6G4pl/x4DTM8BHov7bXjt3yx7ID49cL7 -PCyARLWVoyhFy/qJU3rGcl95YM+0wFrPPD8yC6ElkxQqQKJ+QQszWTpweiXCY+Oa -lvJpbQdCtqRQSVe6AfqylplYMi+QzPaNNTCBxyDw8yIZbW5Rw81pqadDhb0N+XjS -YuA2XMcoC30CgYEAvrMoTYtYH96xQZiuNjh8cKtPLVs4HK+yAd+xYj9upTmRgMHB -2upwgp2ZUvYqRh5d5YCZPUrZuhZBk3c1vDYaiu3AGrGkYy31C7oTem7vUJgNkGov -tHZq9AIpMYUWmvva5mWW6TPxbdnqYA5MhET3n6//Zsrl8LFVrbew3ber+cMCgYB9 -S82OSiJpc0IaY8fsjA3qvwSnKsuKqIaI5LBs2bqFztL5Z+CZqOjLhR5Iiw+0Vf+7 -SZHv5Pn9dHRmjXIkHCadJjy2DB7jfDG8x4b/qFdVX/SL5Qe3w258csOxoiSb6Rks -IC8FqoNZfftZG4xmUhhwxWNH+CdNYc2AUb/cedvjfQKBgQCeH1q+GFY3tgKt8ERE -sInEWc5Hu9+MI1Km57Z64qlpQdR4qgJB+/IXVpPShup2XuRAzAZMUpvDMisD3OOM -2zOsKTA1e2fs8tsK5YaEoG1ZK9/1XTmnBvmCUvwzo0r6V89BVwGRlNKXluogmQv7 -zDeY1HRrDle5BPmKhe3fuZltcg== ------END PRIVATE KEY----- diff --git a/iot/api-client/beta-features/manager/resources/rsa_private_pkcs8 b/iot/api-client/beta-features/manager/resources/rsa_private_pkcs8 deleted file mode 100644 index 92b8cdf4ab4..00000000000 Binary files a/iot/api-client/beta-features/manager/resources/rsa_private_pkcs8 and /dev/null differ diff --git a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExample.java b/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExample.java deleted file mode 100644 index 9118e657f47..00000000000 --- a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExample.java +++ /dev/null @@ -1,832 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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.cloud.iot.examples; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; -import com.google.api.client.http.HttpRequestInitializer; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.cloudiot.v1.CloudIot; -import com.google.api.services.cloudiot.v1.CloudIotScopes; -import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayRequest; -import com.google.api.services.cloudiot.v1.model.BindDeviceToGatewayResponse; -import com.google.api.services.cloudiot.v1.model.Device; -import com.google.api.services.cloudiot.v1.model.DeviceCredential; -import com.google.api.services.cloudiot.v1.model.DeviceRegistry; -import com.google.api.services.cloudiot.v1.model.EventNotificationConfig; -import com.google.api.services.cloudiot.v1.model.GatewayConfig; -import com.google.api.services.cloudiot.v1.model.PublicKeyCredential; -import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayRequest; -import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayResponse; -import com.google.cloud.Role; -import com.google.cloud.pubsub.v1.TopicAdminClient; -import com.google.iam.v1.Binding; -import com.google.pubsub.v1.Topic; -import com.google.pubsub.v1.TopicName; - -// [START iot_mqtt_includes] -import io.jsonwebtoken.JwtBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - -import java.io.IOException; -import java.math.BigInteger; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Properties; - -import org.apache.commons.cli.HelpFormatter; - -import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; -import org.eclipse.paho.client.mqttv3.MqttCallback; -import org.eclipse.paho.client.mqttv3.MqttClient; -import org.eclipse.paho.client.mqttv3.MqttConnectOptions; -import org.eclipse.paho.client.mqttv3.MqttException; -import org.eclipse.paho.client.mqttv3.MqttMessage; -import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; - -import org.joda.time.DateTime; -// [END iot_mqtt_includes] - -/** - * Example of a Device Gateway using Cloud IoT Core - * - *
- * 
- * $ mvn clean compile assembly:single
- * $ mvn exec:java \
- *       -Dexec.mainClass="com.google.cloud.iot.examples.DeviceGatewayExample" \
- *       -Dexec.args="-project_id=my-project-id \
- *                    -pubsub_topic=projects/my-project-id/topics/my-topic-id \
- *                    -ec_public_key_file=/path/to/ec_public.pem \
- *                    -rsa_certificate_file=/path/to/rsa_cert.pem"
- * 
- * 
- */ -public class DeviceGatewayExample { - - static final String APP_NAME = "DeviceGatewayExample"; - - // TODO: ---- The following are required for testing until merged with GA. (START REMOVEME) - /** Creates a topic and grants the IoT service account access. */ - public static Topic createIotTopic(String projectId, String topicId) throws Exception { - // Create a new topic - final TopicName topicName = TopicName.create(projectId, topicId); - - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - final Topic topic = topicAdminClient.createTopic(topicName); - com.google.iam.v1.Policy policy = topicAdminClient.getIamPolicy(topicName.toString()); - // add role -> members binding - Binding binding = - Binding.newBuilder() - .addMembers("serviceAccount:cloud-iot@system.gserviceaccount.com") - .setRole(Role.owner().toString()) - .build(); - - // create updated policy - com.google.iam.v1.Policy updatedPolicy = - com.google.iam.v1.Policy.newBuilder(policy).addBindings(binding).build(); - topicAdminClient.setIamPolicy(topicName.toString(), updatedPolicy); - - System.out.println("Setup topic / policy for: " + topic.getName()); - return topic; - } - } - - /** Create a registry for Cloud IoT. */ - public static void createRegistry( - String cloudRegion, String projectId, String registryName, String pubsubTopicPath) - throws GeneralSecurityException, IOException { - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String projectPath = "projects/" + projectId + "/locations/" + cloudRegion; - final String fullPubsubPath = "projects/" + projectId + "/topics/" + pubsubTopicPath; - - DeviceRegistry registry = new DeviceRegistry(); - EventNotificationConfig notificationConfig = new EventNotificationConfig(); - notificationConfig.setPubsubTopicName(fullPubsubPath); - List notificationConfigs = new ArrayList(); - notificationConfigs.add(notificationConfig); - registry.setEventNotificationConfigs(notificationConfigs); - registry.setId(registryName); - - DeviceRegistry reg = - service.projects().locations().registries().create(projectPath, registry).execute(); - System.out.println("Created registry: " + reg.getName()); - } - - /** Delete this registry from Cloud IoT. */ - public static void deleteRegistry(String cloudRegion, String projectId, String registryName) - throws GeneralSecurityException, IOException { - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - System.out.println("Deleting: " + registryPath); - service.projects().locations().registries().delete(registryPath).execute(); - } - - public static void deleteDevice( - String deviceId, String projectId, String cloudRegion, String registryName) - throws GeneralSecurityException, IOException { - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String devicePath = - String.format( - "projects/%s/locations/%s/registries/%s/devices/%s", - projectId, cloudRegion, registryName, deviceId); - - System.out.println("Deleting device " + devicePath); - service.projects().locations().registries().devices().delete(devicePath).execute(); - } - // TODO: END methods required for tests - - // [START iot_mqtt_jwt] - /** Create a Cloud IoT Core JWT for the given project id, signed with the given RSA key. */ - private static String createJwtRsa(String projectId, String privateKeyFile) - throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { - DateTime now = new DateTime(); - // Create a JWT to authenticate this device. The device will be disconnected after the token - // expires, and will have to reconnect with a new token. The audience field should always be set - // to the GCP project id. - JwtBuilder jwtBuilder = - Jwts.builder() - .setIssuedAt(now.toDate()) - .setExpiration(now.plusMinutes(20).toDate()) - .setAudience(projectId); - - byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile)); - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("RSA"); - - return jwtBuilder.signWith(SignatureAlgorithm.RS256, kf.generatePrivate(spec)).compact(); - } - - /** Create a Cloud IoT Core JWT for the given project id, signed with the given ES key. */ - private static String createJwtEs(String projectId, String privateKeyFile) - throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { - DateTime now = new DateTime(); - // Create a JWT to authenticate this device. The device will be disconnected after the token - // expires, and will have to reconnect with a new token. The audience field should always be set - // to the GCP project id. - JwtBuilder jwtBuilder = - Jwts.builder() - .setIssuedAt(now.toDate()) - .setExpiration(now.plusMinutes(20).toDate()) - .setAudience(projectId); - - byte[] keyBytes = Files.readAllBytes(Paths.get(privateKeyFile)); - PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); - KeyFactory kf = KeyFactory.getInstance("EC"); - - return jwtBuilder.signWith(SignatureAlgorithm.ES256, kf.generatePrivate(spec)).compact(); - } - // [END iot_mqtt_jwt] - - // [START iot_mqtt_configcallback] - static MqttCallback mCallback; - - /** Attaches the callback used when configuration changes occur. */ - public static void attachCallback(MqttClient client, String deviceId) throws MqttException { - mCallback = - new MqttCallback() { - @Override - public void connectionLost(Throwable cause) { - // Do nothing... - } - - @Override - public void messageArrived(String topic, MqttMessage message) throws Exception { - String payload = new String(message.getPayload()); - System.out.println("Payload : " + payload); - // TODO: Insert your parsing / handling of the configuration message here. - } - - @Override - public void deliveryComplete(IMqttDeliveryToken token) { - // Do nothing; - } - }; - - String configTopic = String.format("/devices/%s/config", deviceId); - System.out.println(String.format("Listening on %s", configTopic)); - // The topic gateways receive error updates on. QoS must be 0. - String errorTopic = String.format("/devices/%s/errors", deviceId); - System.out.println(String.format("Listening on %s", errorTopic)); - client.subscribe(errorTopic, 0); - client.subscribe(configTopic, 1); - client.setCallback(mCallback); - } - // [END iot_mqtt_configcallback] - - /** Connects the gateway to the MQTT bridge. */ - public static MqttClient startMqtt( - String mqttBridgeHostname, - int mqttBridgePort, - String projectId, - String cloudRegion, - String registryId, - String gatewayId, - String privateKeyFile, - String algorithm) - throws NoSuchAlgorithmException, IOException, MqttException, InterruptedException, - InvalidKeySpecException { - // [START iot_gateway_start_mqtt] - - // Build the connection string for Google's Cloud IoT Core MQTT server. Only SSL - // connections are accepted. For server authentication, the JVM's root certificates - // are used. - final String mqttServerAddress = - String.format("ssl://%s:%s", mqttBridgeHostname, mqttBridgePort); - - // Create our MQTT client. The mqttClientId is a unique string that identifies this device. For - // Google Cloud IoT Core, it must be in the format below. - final String mqttClientId = - String.format( - "projects/%s/locations/%s/registries/%s/devices/%s", - projectId, cloudRegion, registryId, gatewayId); - - MqttConnectOptions connectOptions = new MqttConnectOptions(); - // Note that the Google Cloud IoT Core only supports MQTT 3.1.1, and Paho requires that we - // explictly set this. If you don't set MQTT version, the server will immediately close its - // connection to your device. - connectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); - - Properties sslProps = new Properties(); - sslProps.setProperty("com.ibm.ssl.protocol", "TLSv1.2"); - connectOptions.setSSLProperties(sslProps); - - // With Google Cloud IoT Core, the username field is ignored, however it must be set for the - // Paho client library to send the password field. The password field is used to transmit a JWT - // to authorize the device. - connectOptions.setUserName("unused"); - - DateTime iat = new DateTime(); - if (algorithm.equals("RS256")) { - connectOptions.setPassword(createJwtRsa(projectId, privateKeyFile).toCharArray()); - } else if (algorithm.equals("ES256")) { - connectOptions.setPassword(createJwtEs(projectId, privateKeyFile).toCharArray()); - } else { - throw new IllegalArgumentException( - "Invalid algorithm " + algorithm + ". Should be one of 'RS256' or 'ES256'."); - } - - System.out.println(String.format(mqttClientId)); - - // Create a client, and connect to the Google MQTT bridge. - MqttClient client = new MqttClient(mqttServerAddress, mqttClientId, new MemoryPersistence()); - - // Both connect and publish operations may fail. If they do, allow retries but with an - // exponential backoff time period. - long initialConnectIntervalMillis = 500L; - long maxConnectIntervalMillis = 6000L; - long maxConnectRetryTimeElapsedMillis = 900000L; - float intervalMultiplier = 1.5f; - - long retryIntervalMs = initialConnectIntervalMillis; - long totalRetryTimeMs = 0; - - while (!client.isConnected() && totalRetryTimeMs < maxConnectRetryTimeElapsedMillis) { - try { - client.connect(connectOptions); - } catch (MqttException e) { - int reason = e.getReasonCode(); - - // If the connection is lost or if the server cannot be connected, allow retries, but with - // exponential backoff. - System.out.println("An error occurred: " + e.getMessage()); - if (reason == MqttException.REASON_CODE_CONNECTION_LOST - || reason == MqttException.REASON_CODE_SERVER_CONNECT_ERROR) { - System.out.println("Retrying in " + retryIntervalMs / 1000.0 + " seconds."); - Thread.sleep(retryIntervalMs); - totalRetryTimeMs += retryIntervalMs; - retryIntervalMs *= intervalMultiplier; - if (retryIntervalMs > maxConnectIntervalMillis) { - retryIntervalMs = maxConnectIntervalMillis; - } - } else { - throw e; - } - } - } - - attachCallback(client, gatewayId); - return client; - // [END iot_gateway_start_mqtt] - } - - public static void bindDeviceToGateway( - String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) - throws GeneralSecurityException, IOException { - // [START bind_device_to_gateway] - createDevice(projectId, cloudRegion, registryName, deviceId); - - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - BindDeviceToGatewayRequest request = new BindDeviceToGatewayRequest(); - request.setDeviceId(deviceId); - request.setGatewayId(gatewayId); - - BindDeviceToGatewayResponse response = - service - .projects() - .locations() - .registries() - .bindDeviceToGateway(registryPath, request) - .execute(); - - System.out.println(String.format("Device bound: %s", response.toPrettyString())); - // [END bind_device_to_gateway] - } - - public static void unbindDeviceFromGateway( - String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) - throws GeneralSecurityException, IOException { - // [START unbind_device_from_gateway] - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - UnbindDeviceFromGatewayRequest request = new UnbindDeviceFromGatewayRequest(); - request.setDeviceId(deviceId); - request.setGatewayId(gatewayId); - - UnbindDeviceFromGatewayResponse response = - service - .projects() - .locations() - .registries() - .unbindDeviceFromGateway(registryPath, request) - .execute(); - - System.out.println(String.format("Device unbound: %s", response.toPrettyString())); - // [END unbind_device_from_gateway] - } - - public static void sendDataFromDevice( - MqttClient client, String deviceId, String messageType, String data) throws MqttException { - // [START send_data_from_bound_device] - if (!messageType.equals("events") && !messageType.equals("state")) { - System.err.println("Invalid message type, must ether be 'state' or events'"); - return; - } - final String dataTopic = String.format("/devices/%s/%s", deviceId, messageType); - MqttMessage message = new MqttMessage(data.getBytes()); - message.setQos(1); - client.publish(dataTopic, message); - System.out.println("Data sent"); - // [END send_data_from_bound_device] - } - - public static void attachDeviceToGateway(MqttClient client, String deviceId) - throws MqttException { - // [START attach_device] - final String attachTopic = String.format("/devices/%s/attach", deviceId); - System.out.println(String.format("Attaching: %s", attachTopic)); - String attachPayload = "{}"; - MqttMessage message = new MqttMessage(attachPayload.getBytes()); - message.setQos(1); - client.publish(attachTopic, message); - // [END attach_device] - } - - /** Detaches a bound device from the Gateway. */ - public static void detachDeviceFromGateway(MqttClient client, String deviceId) - throws MqttException { - // [START detach_device] - final String detachTopic = String.format("/devices/%s/detach", deviceId); - System.out.println(String.format("Detaching: %s", detachTopic)); - String attachPayload = "{}"; - MqttMessage message = new MqttMessage(attachPayload.getBytes()); - message.setQos(1); - client.publish(detachTopic, message); - // [END detach_device] - } - - /** Create a device to bind to a gateway. */ - public static void createDevice( - String projectId, String cloudRegion, String registryName, String deviceId) - throws GeneralSecurityException, IOException { - // [START create_device] - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - List devices = - service - .projects() - .locations() - .registries() - .devices() - .list(registryPath) - .setFieldMask("config,gatewayConfig") - .execute() - .getDevices(); - - if (devices != null) { - System.out.println("Found " + devices.size() + " devices"); - for (Device d : devices) { - if ((d.getId() != null && d.getId().equals(deviceId)) - || (d.getName() != null && d.getName().equals(deviceId))) { - System.out.println("Device exists, skipping."); - return; - } - } - } - - System.out.println("Creating device with id: " + deviceId); - Device device = new Device(); - device.setId(deviceId); - - GatewayConfig gwConfig = new GatewayConfig(); - gwConfig.setGatewayType("NON_GATEWAY"); - gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); - - device.setGatewayConfig(gwConfig); - Device createdDevice = - service - .projects() - .locations() - .registries() - .devices() - .create(registryPath, device) - .execute(); - - System.out.println("Created device: " + createdDevice.toPrettyString()); - // [END create_device] - } - - /** Create a gateway to bind devices to. */ - public static void createGateway( - String projectId, - String cloudRegion, - String registryName, - String gatewayId, - String certificateFilePath, - String algorithm) - throws GeneralSecurityException, IOException { - // [START create_gateway] - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - System.out.println("Creating gateway with id: " + gatewayId); - Device device = new Device(); - device.setId(gatewayId); - - GatewayConfig gwConfig = new GatewayConfig(); - gwConfig.setGatewayType("GATEWAY"); - gwConfig.setGatewayAuthMethod("ASSOCIATION_ONLY"); - - String keyFormat = "RSA_X509_PEM"; - if (algorithm == "ES256") { - keyFormat = "ES256_PEM"; - } - - PublicKeyCredential publicKeyCredential = new PublicKeyCredential(); - - byte[] keyBytes = Files.readAllBytes(Paths.get(certificateFilePath)); - publicKeyCredential.setKey(new String(keyBytes)); - publicKeyCredential.setFormat(keyFormat); - DeviceCredential deviceCredential = new DeviceCredential(); - deviceCredential.setPublicKey(publicKeyCredential); - - device.setGatewayConfig(gwConfig); - device.setCredentials(Arrays.asList(deviceCredential)); - Device createdDevice = - service - .projects() - .locations() - .registries() - .devices() - .create(registryPath, device) - .execute(); - - System.out.println("Created gateway: " + createdDevice.toPrettyString()); - // [END create_gateway] - } - - public static void listGateways(String projectId, String cloudRegion, String registryName) - throws IOException, GeneralSecurityException { - // [START list_gateways] - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - List devices = - service - .projects() - .locations() - .registries() - .devices() - .list(registryPath) - .setFieldMask("config,gatewayConfig") - .execute() - .getDevices(); - - if (devices != null) { - System.out.println("Found " + devices.size() + " devices"); - for (Device d : devices) { - if (d.getGatewayConfig() != null - && d.getGatewayConfig().getGatewayType() != null - && d.getGatewayConfig().getGatewayType().equals("GATEWAY")) { - System.out.println("Id: " + d.getId()); - if (d.getConfig() != null) { - // Note that this will show the device config in Base64 encoded format. - System.out.println("Config: " + d.getGatewayConfig().toPrettyString()); - } - System.out.println(); - } - } - } else { - System.out.println("Registry has no devices."); - } - // [END list_gateways] - } - - /** List devices bound to a gateway. */ - public static void listDevicesForGateway( - String projectId, String cloudRegion, String registryName, String gatewayId) - throws IOException, GeneralSecurityException { - // [START list_devices_for_gateway] - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); - JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); - HttpRequestInitializer init = new RetryHttpInitializerWrapper(credential); - final CloudIot service = - new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init) - .setApplicationName(APP_NAME) - .build(); - - final String gatewayPath = - String.format( - "projects/%s/locations/%s/registries/%s/devices/%s", - projectId, cloudRegion, registryName, gatewayId); - - final String registryPath = - String.format( - "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - - List deviceNumIds = - service - .projects() - .locations() - .registries() - .devices() - .list(registryPath) - .setGatewayListOptionsAssociationsGatewayId(gatewayId) - .execute() - .getDevices(); - - if (deviceNumIds != null) { - System.out.println("Found " + deviceNumIds.size() + " devices"); - for (Device device : deviceNumIds) { - System.out.println(String.format("ID: %s", device.getId())); - } - } else { - System.out.println("Gateway has no bound devices."); - } - // [END list_devices_for_gateway] - } - - /** Sends data on behalf of a bound device using the Gateway. */ - public static void sendDataFromBoundDevice( - String mqttBridgeHostname, - short mqttBridgePort, - String projectId, - String cloudRegion, - String registryName, - String gatewayId, - String privateKeyFile, - String algorithm, - String deviceId, - String messageType, - String telemetryData) - throws MqttException, IOException, InvalidKeySpecException, InterruptedException, - NoSuchAlgorithmException { - // [START send_data_from_bound_device] - MqttClient client = - startMqtt( - mqttBridgeHostname, - mqttBridgePort, - projectId, - cloudRegion, - registryName, - gatewayId, - privateKeyFile, - algorithm); - attachDeviceToGateway(client, deviceId); - sendDataFromDevice(client, deviceId, messageType, telemetryData); - detachDeviceFromGateway(client, deviceId); - // [END send_data_from_bound_device] - } - - public static void listenForConfigMessages( - String mqttBridgeHostname, - short mqttBridgePort, - String projectId, - String cloudRegion, - String registryName, - String gatewayId, - String privateKeyFile, - String algorithm, - String deviceId) - throws MqttException, IOException, InvalidKeySpecException, InterruptedException, - NoSuchAlgorithmException { - // Connect the Gateway - MqttClient client = - startMqtt( - mqttBridgeHostname, - mqttBridgePort, - projectId, - cloudRegion, - registryName, - gatewayId, - privateKeyFile, - algorithm); - // Connect the bound device and listen for configuration messages. - attachDeviceToGateway(client, deviceId); - attachCallback(client, deviceId); - - detachDeviceFromGateway(client, deviceId); - } - - /** Entry poit for CLI. */ - public static void main(String[] args) throws Exception { - DeviceGatewayExampleOptions options = DeviceGatewayExampleOptions.fromFlags(args); - - if (options == null) { - // Could not parse. - return; - } - - switch (options.command) { - case "bind-device-to-gateway": - System.out.println("Binding device to gateway:"); - bindDeviceToGateway( - options.projectId, - options.cloudRegion, - options.registryName, - options.deviceId, - options.gatewayId); - break; - case "create-gateway": - System.out.println("Creating Gateway:"); - createGateway( - options.projectId, - options.cloudRegion, - options.registryName, - options.gatewayId, - options.publicKeyFile, - options.algorithm); - break; - case "list-gateways": - System.out.println("Listing gateways:"); - listGateways(options.projectId, options.cloudRegion, options.registryName); - break; - case "list-devices-for-gateway": - System.out.println("Listing devices for gateway:"); - listDevicesForGateway( - options.projectId, options.cloudRegion, options.registryName, options.gatewayId); - break; - case "listen-for-config-messages": - System.out.println( - String.format("Listening for configuration messages for %s:", options.deviceId)); - listenForConfigMessages( - options.mqttBridgeHostname, - options.mqttBridgePort, - options.projectId, - options.cloudRegion, - options.registryName, - options.gatewayId, - options.privateKeyFile, - options.algorithm, - options.deviceId); - break; - case "send-data-from-bound-device": - System.out.println("Sending data on behalf of device:"); - sendDataFromBoundDevice( - options.mqttBridgeHostname, - options.mqttBridgePort, - options.projectId, - options.cloudRegion, - options.registryName, - options.gatewayId, - options.privateKeyFile, - options.algorithm, - options.deviceId, - options.messageType, - options.telemetryData); - break; - case "unbind-device-from-gateway": - System.out.println("Unbinding device from gateway:"); - unbindDeviceFromGateway( - options.projectId, - options.cloudRegion, - options.registryName, - options.deviceId, - options.gatewayId); - break; - default: - String header = "Cloud IoT Core Commandline Example (Device Gateway Example): \n\n"; - String footer = "\nhttps://cloud.google.com/iot-core"; - - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceGatewayExample", header, options.options, footer, true); - break; - } - } -} diff --git a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExampleOptions.java b/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExampleOptions.java deleted file mode 100644 index f7d359c2abe..00000000000 --- a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExampleOptions.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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.cloud.iot.examples; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; - -/** Command line options for the Device Manager example. */ -public class DeviceGatewayExampleOptions { - String algorithm; - String cloudRegion = "us-central1"; - String command = "help"; - String deviceId; // Default to UUID? - String gatewayId; - String projectId; - String publicKeyFile; - String privateKeyFile; - String registryName; - String telemetryData = "Specify with -telemetry_data"; - - String mqttBridgeHostname = "mqtt.googleapis.com"; - short mqttBridgePort = 8883; - int numMessages = 10; - int tokenExpMins = 60; - String messageType = "event"; - - - static final Options options = new Options(); - - /** Construct an DeviceGatewayExampleOptions class from command line flags. */ - public static DeviceGatewayExampleOptions fromFlags(String[] args) { - // Required arguments - options.addOption( - Option.builder() - .type(String.class) - .longOpt("command") - .hasArg() - .desc( - "Command to run:" - + "\n\tbind-device-to-gateway" - + "\n\tcreate-gateway" - + "\n\tlist-gateways" - + "\n\tlist-devices-for-gateway" - + "\n\tlisten-for-config-messages" - + "\n\tsend-data-from-bound-device" - + "\n\tunbind-device-from-gateway") - .required() - .build()); - // Optional arguments. - options.addOption( - Option.builder() - .type(String.class) - .longOpt("algorithm") - .hasArg() - .desc("Algorithm used for public/private keys.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("cloud_region") - .hasArg() - .desc("GCP cloud region.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("device_id") - .hasArg() - .desc("The identifier for the device bound to the gateway.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("gateway_id") - .hasArg() - .desc("The identifier for the Gateway.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("project_id") - .hasArg() - .desc("GCP cloud project name.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("private_key_file") - .hasArg() - .desc("Private key file used for connecting devices and gateways.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("public_key_file") - .hasArg() - .desc("Public key file used for registering devices and gateways.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("registry_name") - .hasArg() - .desc("Name for your Device Registry.") - .build()); - - options.addOption( - Option.builder() - .type(String.class) - .longOpt("telemetry_data") - .hasArg() - .desc("The telemetry data (string or JSON) to send on behalf of the delegated device.") - .build()); - options.addOption( - Option.builder() - .type(Number.class) - .longOpt("num_messages") - .hasArg() - .desc("Number of messages to publish.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("mqtt_bridge_hostname") - .hasArg() - .desc("MQTT bridge hostname.") - .build()); - options.addOption( - Option.builder() - .type(Number.class) - .longOpt("token_exp_minutes") - .hasArg() - .desc("Minutes to JWT token refresh (token expiration time).") - .build()); - options.addOption( - Option.builder() - .type(Number.class) - .longOpt("mqtt_bridge_port") - .hasArg() - .desc("MQTT bridge port.") - .build()); - options.addOption( - Option.builder() - .type(String.class) - .longOpt("message_type") - .hasArg() - .desc("Indicates whether the message is a telemetry event or a device state message") - .build()); - - - CommandLineParser parser = new DefaultParser(); - CommandLine commandLine; - try { - commandLine = parser.parse(options, args); - DeviceGatewayExampleOptions res = new DeviceGatewayExampleOptions(); - - res.command = commandLine.getOptionValue("command"); - - if (res.command.equals("help") || res.command.equals("")) { - throw new ParseException("Invalid command, showing help."); - } - - if (commandLine.hasOption("algorithm")) { - res.algorithm = commandLine.getOptionValue("algorithm"); - } - if (commandLine.hasOption("cloud_region")) { - res.cloudRegion = commandLine.getOptionValue("cloud_region"); - } - if (commandLine.hasOption("telemetry_data")) { - res.telemetryData = commandLine.getOptionValue("telemetry_data"); - } - if (commandLine.hasOption("device_id")) { - res.deviceId = commandLine.getOptionValue("device_id"); - } - if (commandLine.hasOption("gateway_id")) { - res.gatewayId = commandLine.getOptionValue("gateway_id"); - } - if (commandLine.hasOption("project_id")) { - res.projectId = commandLine.getOptionValue("project_id"); - } else { - try { - res.projectId = System.getenv("GOOGLE_CLOUD_PROJECT"); - } catch (NullPointerException npe) { - res.projectId = System.getenv("GCLOUD_PROJECT"); - } - } - if (commandLine.hasOption("private_key_file")) { - res.privateKeyFile = commandLine.getOptionValue("private_key_file"); - } - if (commandLine.hasOption("public_key_file")) { - res.publicKeyFile = commandLine.getOptionValue("public_key_file"); - } - if (commandLine.hasOption("registry_name")) { - res.registryName = commandLine.getOptionValue("registry_name"); - } - if (commandLine.hasOption("num_messages")) { - res.numMessages = ((Number) commandLine.getParsedOptionValue("num_messages")).intValue(); - } - if (commandLine.hasOption("token_exp_minutes")) { - res.tokenExpMins = - ((Number) commandLine.getParsedOptionValue("token_exp_minutes")).intValue(); - } - if (commandLine.hasOption("mqtt_bridge_hostname")) { - res.mqttBridgeHostname = commandLine.getOptionValue("mqtt_bridge_hostname"); - } - if (commandLine.hasOption("mqtt_bridge_port")) { - res.mqttBridgePort = - ((Number) commandLine.getParsedOptionValue("mqtt_bridge_port")).shortValue(); - } - if (commandLine.hasOption("message_type")) { - res.messageType = commandLine.getOptionValue("message_type"); - } - - return res; - } catch (ParseException e) { - String header = "Cloud IoT Core Commandline Example (Device Gateways): \n\n"; - String footer = "\nhttps://cloud.google.com/iot-core"; - - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("DeviceGatewayExample", header, options, footer, - true); - - System.err.println(e.getMessage()); - return null; - } - } -} diff --git a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java b/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java deleted file mode 100644 index 10cbb336a70..00000000000 --- a/iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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.cloud.iot.examples; - -import com.google.api.client.auth.oauth2.Credential; -import com.google.api.client.http.HttpBackOffIOExceptionHandler; -import com.google.api.client.http.HttpBackOffUnsuccessfulResponseHandler; -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpRequestInitializer; -import com.google.api.client.http.HttpResponse; -import com.google.api.client.http.HttpUnsuccessfulResponseHandler; -import com.google.api.client.util.ExponentialBackOff; -import com.google.api.client.util.Sleeper; -import com.google.common.base.Preconditions; - -import java.io.IOException; -import java.util.logging.Logger; - -/** - * RetryHttpInitializerWrapper will automatically retry upon RPC failures, preserving the - * auto-refresh behavior of the Google Credentials. - */ -public class RetryHttpInitializerWrapper implements HttpRequestInitializer { - - /** A private logger. */ - private static final Logger LOG = Logger.getLogger(RetryHttpInitializerWrapper.class.getName()); - - /** One minutes in milliseconds. */ - private static final int ONE_MINUTE_MILLIS = 60 * 1000; - - /** - * Intercepts the request for filling in the "Authorization" header field, as well as recovering - * from certain unsuccessful error codes wherein the Credential must refresh its token for a - * retry. - */ - private final Credential wrappedCredential; - - /** A sleeper; you can replace it with a mock in your test. */ - private final Sleeper sleeper; - - /** - * A constructor. - * - * @param wrappedCredential Credential which will be wrapped and used for providing auth header. - */ - public RetryHttpInitializerWrapper(final Credential wrappedCredential) { - this(wrappedCredential, Sleeper.DEFAULT); - } - - /** - * A protected constructor only for testing. - * - * @param wrappedCredential Credential which will be wrapped and used for providing auth header. - * @param sleeper Sleeper for easy testing. - */ - RetryHttpInitializerWrapper(final Credential wrappedCredential, final Sleeper sleeper) { - this.wrappedCredential = Preconditions.checkNotNull(wrappedCredential); - this.sleeper = sleeper; - } - - /** Initializes the given request. */ - @Override - public final void initialize(final HttpRequest request) { - request.setReadTimeout(2 * ONE_MINUTE_MILLIS); // 2 minutes read timeout - final HttpUnsuccessfulResponseHandler backoffHandler = - new HttpBackOffUnsuccessfulResponseHandler(new ExponentialBackOff()).setSleeper(sleeper); - request.setInterceptor(wrappedCredential); - request.setUnsuccessfulResponseHandler( - new HttpUnsuccessfulResponseHandler() { - @Override - public boolean handleResponse( - final HttpRequest request, final HttpResponse response, final boolean supportsRetry) - throws IOException { - if (wrappedCredential.handleResponse(request, response, supportsRetry)) { - // If credential decides it can handle it, the return code or message indicated - // something specific to authentication, and no backoff is desired. - return true; - } else if (backoffHandler.handleResponse(request, response, supportsRetry)) { - // Otherwise, we defer to the judgment of our internal backoff handler. - LOG.info("Retrying " + request.getUrl().toString()); - return true; - } else { - return false; - } - } - }); - request.setIOExceptionHandler( - new HttpBackOffIOExceptionHandler(new ExponentialBackOff()).setSleeper(sleeper)); - } -} diff --git a/iot/api-client/beta-features/manager/src/test/java/com/example/cloud/iot/examples/GatewayIT.java b/iot/api-client/beta-features/manager/src/test/java/com/example/cloud/iot/examples/GatewayIT.java deleted file mode 100644 index 2f360eb781a..00000000000 --- a/iot/api-client/beta-features/manager/src/test/java/com/example/cloud/iot/examples/GatewayIT.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * 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.cloud.iot.examples; - -import com.google.api.services.cloudiot.v1.model.Device; -import com.google.cloud.pubsub.v1.TopicAdminClient; -import com.google.pubsub.v1.Topic; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import org.eclipse.paho.client.mqttv3.MqttClient; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for iot "Management" sample. */ -@RunWith(JUnit4.class) -@SuppressWarnings("checkstyle:abbreviationaswordinname") -public class GatewayIT { - private ByteArrayOutputStream bout; - private PrintStream out; - - private static final String CLOUD_REGION = "us-central1"; - private static final String ES_PATH = "resources/ec_public.pem"; - private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); - private static final String REGISTRY_ID = "java-reg-" + (System.currentTimeMillis() / 1000L); - private static final String RSA_PATH = "resources/rsa_cert.pem"; - private static final String PKCS_PATH = "resources/rsa_private_pkcs8"; - private static final String TOPIC_ID = "java-pst-" + (System.currentTimeMillis() / 1000L); - private static final String MEMBER = "group:dpebot@google.com"; - private static final String ROLE = "roles/viewer"; - - - private static Topic topic; - - @Before - public void setUp() throws Exception { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - } - - @After - public void tearDown() throws Exception { - System.setOut(null); - } - - // Manager tests - @Test - public void testCreateGateway() throws Exception { - final String gatewayName = "rsa-create-gateway"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); - - // Assertions - String got = bout.toString(); - System.out.println(got); - Assert.assertTrue(got.contains("Created gateway:")); - - // Clean up - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - topicAdminClient.deleteTopic(topic.getNameAsTopicName()); - } - } - - @Test - public void testListGateways() throws Exception { - final String gatewayName = "rsa-list-gateway"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); - DeviceGatewayExample.listGateways(PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - - // Assertions - String got = bout.toString(); - System.out.println(got); - Assert.assertTrue(got.contains("Found 1 devices")); - Assert.assertTrue(got.contains(String.format("Id: %s", gatewayName))); - - // Clean up - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - topicAdminClient.deleteTopic(topic.getNameAsTopicName()); - } - } - - @Test - public void testBindDeviceToGatewayAndUnbind() throws Exception { - final String gatewayName = "rsa-bind-gateway"; - final String deviceName = "rsa-bind-device"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); - DeviceGatewayExample.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName); - DeviceGatewayExample.bindDeviceToGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - DeviceGatewayExample.unbindDeviceFromGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - - // Assertions - String got = bout.toString(); - System.out.println(got); - Assert.assertTrue(got.contains("Device bound: ")); - Assert.assertTrue(got.contains("Device unbound: ")); - - // Clean up - DeviceGatewayExample.deleteDevice(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - topicAdminClient.deleteTopic(topic.getNameAsTopicName()); - } - } - - // MQTT device tests - @Test - public void testGatewayListenForDevice() throws Exception { - final String gatewayName = "rsa-listen-gateway"; - final String deviceName = "rsa-listen-device"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); - DeviceGatewayExample.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName); - DeviceGatewayExample.bindDeviceToGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - - Thread deviceThread = new Thread() { - public void run() { - try { - DeviceGatewayExample.listenForConfigMessages( - "mqtt.googleapis.com", (short)443, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, - PKCS_PATH, "RS256", deviceName); - } catch (Exception e) { - // TODO: Fail - System.out.println("Failure on Exception"); - } - } - }; - deviceThread.start(); - Thread.sleep(3000); // Give the device a chance to connect / receive configurations - deviceThread.join(); - - // Assertions - String got = bout.toString(); - System.out.println(got); - Assert.assertTrue(got.contains("Payload")); - - // Clean up - DeviceGatewayExample.unbindDeviceFromGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - DeviceGatewayExample.deleteDevice(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - topicAdminClient.deleteTopic(topic.getNameAsTopicName()); - } - } - - @Test - public void testErrorTopic() throws Exception { - final String gatewayName = "rsa-listen-gateway-test"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, - gatewayName, RSA_PATH, "RS256"); - MqttClient client = DeviceGatewayExample.startMqtt("mqtt.googleapis.com", (short)443, - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, PKCS_PATH, "RS256"); - - - Thread deviceThread = new Thread() { - public void run() { - try { - DeviceGatewayExample.attachDeviceToGateway(client, "garbage-device"); - DeviceGatewayExample.attachCallback(client, "garbage-device"); - } catch (Exception e) { - // TODO: Fail - System.out.println("Failure on Exception :" + e.toString()); - } - } - }; - - deviceThread.start(); - Thread.sleep(4000); - - String got = bout.toString(); - Assert.assertTrue(got.contains("error_type")); - - //Clean up - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - } - - @Test - public void testSendDataForBoundDevice() throws Exception { - final String gatewayName = "rsa-send-gateway"; - final String deviceName = "rsa-send-device"; - topic = DeviceGatewayExample.createIotTopic(PROJECT_ID, TOPIC_ID); - DeviceGatewayExample.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID); - DeviceGatewayExample.createGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, RSA_PATH, "RS256"); - DeviceGatewayExample.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName); - DeviceGatewayExample.bindDeviceToGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - - Thread deviceThread = new Thread() { - public void run() { - try { - DeviceGatewayExample.sendDataFromBoundDevice( - "mqtt.googleapis.com", (short)443, PROJECT_ID, CLOUD_REGION, REGISTRY_ID, gatewayName, - PKCS_PATH, "RS256", deviceName, "state", "Cookies are delish"); - } catch (Exception e) { - // TODO: Fail - System.out.println("Failure on Exception"); - } - } - }; - deviceThread.start(); - Thread.sleep(3000); // Give the device a chance to connect / receive configurations - deviceThread.join(); - - // Assertions - String got = bout.toString(); - System.out.println(got); - Assert.assertTrue(got.contains("Data sent")); - - // Clean up - DeviceGatewayExample.unbindDeviceFromGateway( - PROJECT_ID, CLOUD_REGION, REGISTRY_ID, deviceName, gatewayName); - DeviceGatewayExample.deleteDevice(deviceName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteDevice(gatewayName, PROJECT_ID, CLOUD_REGION, REGISTRY_ID); - DeviceGatewayExample.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID); - try (TopicAdminClient topicAdminClient = TopicAdminClient.create()) { - topicAdminClient.deleteTopic(topic.getNameAsTopicName()); - } - } -} diff --git a/iot/api-client/codelab/manager/pom.xml b/iot/api-client/codelab/manager/pom.xml index 5c2b216c416..8f47046d101 100644 --- a/iot/api-client/codelab/manager/pom.xml +++ b/iot/api-client/codelab/manager/pom.xml @@ -30,7 +30,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/iot/api-client/end-to-end-example/pom.xml b/iot/api-client/end-to-end-example/pom.xml index 29f08246186..0272e387d9c 100644 --- a/iot/api-client/end-to-end-example/pom.xml +++ b/iot/api-client/end-to-end-example/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/iot/api-client/manager/pom.xml b/iot/api-client/manager/pom.xml index 3ea79c6a314..3130ccd2cec 100644 --- a/iot/api-client/manager/pom.xml +++ b/iot/api-client/manager/pom.xml @@ -30,8 +30,9 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 + 1.8 1.8 diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java index dd03c323fd1..2963a58eb98 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExample.java @@ -42,6 +42,7 @@ import com.google.api.services.cloudiot.v1.model.SetIamPolicyRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayRequest; import com.google.api.services.cloudiot.v1.model.UnbindDeviceFromGatewayResponse; + import com.google.cloud.Role; import com.google.cloud.pubsub.v1.TopicAdminClient; import com.google.common.io.Files; @@ -57,11 +58,8 @@ import java.util.Arrays; import java.util.Base64; import java.util.List; -import org.apache.commons.cli.HelpFormatter; -import org.eclipse.paho.client.mqttv3.MqttClient; -import org.eclipse.paho.client.mqttv3.MqttException; -import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.apache.commons.cli.HelpFormatter; /** * Example of using Cloud IoT device manager API to administer devices, registries and projects. * @@ -93,6 +91,7 @@ * * */ + public class DeviceRegistryExample { static final String APP_NAME = "DeviceRegistryExample"; @@ -780,7 +779,7 @@ public static void setIamPermissions( // [END iot_set_iam_policy] /** Send a command to a device. * */ - // [START send_command] + // [START iot_send_command] public static void sendCommand( String deviceId, String projectId, String cloudRegion, String registryName, String data) throws GeneralSecurityException, IOException { @@ -817,12 +816,12 @@ public static void sendCommand( System.out.println("Command response: " + res.toString()); } - // [END send_command] + // [END iot_send_command] public static void bindDeviceToGateway( String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) throws GeneralSecurityException, IOException { - // [START bind_device_to_gateway] + // [START iot_bind_device_to_gateway] createDevice(projectId, cloudRegion, registryName, deviceId); GoogleCredential credential = @@ -851,13 +850,13 @@ public static void bindDeviceToGateway( .execute(); System.out.println(String.format("Device bound: %s", response.toPrettyString())); - // [END bind_device_to_gateway] + // [END iot_bind_device_to_gateway] } public static void unbindDeviceFromGateway( String projectId, String cloudRegion, String registryName, String deviceId, String gatewayId) throws GeneralSecurityException, IOException { - // [START unbind_device_from_gateway] + // [START iot_unbind_device_from_gateway] GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); @@ -884,39 +883,14 @@ public static void unbindDeviceFromGateway( .execute(); System.out.println(String.format("Device unbound: %s", response.toPrettyString())); - // [END unbind_device_from_gateway] - } - - public static void attachDeviceToGateway(MqttClient client, String deviceId) - throws MqttException { - // [START attach_device] - final String attachTopic = String.format("/devices/%s/attach", deviceId); - System.out.println(String.format("Attaching: %s", attachTopic)); - String attachPayload = "{}"; - MqttMessage message = new MqttMessage(attachPayload.getBytes()); - message.setQos(1); - client.publish(attachTopic, message); - // [END attach_device] - } - - /** Detaches a bound device from the Gateway. */ - public static void detachDeviceFromGateway(MqttClient client, String deviceId) - throws MqttException { - // [START detach_device] - final String detachTopic = String.format("/devices/%s/detach", deviceId); - System.out.println(String.format("Detaching: %s", detachTopic)); - String attachPayload = "{}"; - MqttMessage message = new MqttMessage(attachPayload.getBytes()); - message.setQos(1); - client.publish(detachTopic, message); - // [END detach_device] + // [END iot_unbind_device_from_gateway] } /** Create a device to bind to a gateway. */ public static void createDevice( String projectId, String cloudRegion, String registryName, String deviceId) throws GeneralSecurityException, IOException { - // [START create_device] + // [START iot_create_device] GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); @@ -971,7 +945,7 @@ public static void createDevice( .execute(); System.out.println("Created device: " + createdDevice.toPrettyString()); - // [END create_device] + // [END iot_create_device] } /** Create a gateway to bind devices to. */ @@ -983,7 +957,7 @@ public static void createGateway( String certificateFilePath, String algorithm) throws GeneralSecurityException, IOException { - // [START create_gateway] + // [START iot_create_gateway] GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); @@ -1030,12 +1004,12 @@ public static void createGateway( .execute(); System.out.println("Created gateway: " + createdDevice.toPrettyString()); - // [END create_gateway] + // [END iot_create_gateway] } public static void listGateways(String projectId, String cloudRegion, String registryName) throws IOException, GeneralSecurityException { - // [START list_gateways] + // [START iot_list_gateways] GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); @@ -1049,42 +1023,38 @@ public static void listGateways(String projectId, String cloudRegion, String reg String.format( "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); - List devices = + List gateways = service .projects() .locations() .registries() .devices() .list(registryPath) - .setFieldMask("config,gatewayConfig") + .setGatewayListOptionsGatewayType("GATEWAY") .execute() .getDevices(); - if (devices != null) { - System.out.println("Found " + devices.size() + " devices"); - for (Device d : devices) { - if (d.getGatewayConfig() != null - && d.getGatewayConfig().getGatewayType() != null - && d.getGatewayConfig().getGatewayType().equals("GATEWAY")) { - System.out.println("Id: " + d.getId()); - if (d.getConfig() != null) { - // Note that this will show the device config in Base64 encoded format. - System.out.println("Config: " + d.getGatewayConfig().toPrettyString()); - } - System.out.println(); + if (gateways != null) { + System.out.println("Found " + gateways.size() + " devices"); + for (Device d : gateways) { + System.out.println("Id: " + d.getId()); + if (d.getConfig() != null) { + // Note that this will show the device config in Base64 encoded format. + System.out.println("Config: " + d.getGatewayConfig().toPrettyString()); } + System.out.println(); } } else { System.out.println("Registry has no devices."); } - // [END list_gateways] + // [END iot_list_gateways] } /** List devices bound to a gateway. */ public static void listDevicesForGateway( String projectId, String cloudRegion, String registryName, String gatewayId) throws IOException, GeneralSecurityException { - // [START list_devices_for_gateway] + // [START iot_list_devices_for_gateway] GoogleCredential credential = GoogleCredential.getApplicationDefault().createScoped(CloudIotScopes.all()); JsonFactory jsonFactory = JacksonFactory.getDefaultInstance(); @@ -1094,11 +1064,6 @@ public static void listDevicesForGateway( .setApplicationName(APP_NAME) .build(); - final String gatewayPath = - String.format( - "projects/%s/locations/%s/registries/%s/devices/%s", - projectId, cloudRegion, registryName, gatewayId); - final String registryPath = String.format( "projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName); @@ -1122,7 +1087,7 @@ public static void listDevicesForGateway( } else { System.out.println("Gateway has no bound devices."); } - // [END list_devices_for_gateway] + // [END iot_list_devices_for_gateway] } /** Entry poit for CLI. */ @@ -1253,6 +1218,15 @@ public static void main(String[] args) throws Exception { options.role); } break; + case "list-gateways": + System.out.println("Listing gateways: "); + listGateways(options.projectId, options.cloudRegion, options.registryName); + break; + case "list-devices-for-gateway": + System.out.println("Listing devices for a gateway: "); + listDevicesForGateway( + options.projectId, options.cloudRegion, options.registryName, options.gatewayId); + break; case "send-command": System.out.println("Sending command to device:"); sendCommand( diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java index 5a4c7270845..6df8db2e1c6 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/DeviceRegistryExampleOptions.java @@ -35,6 +35,7 @@ public class DeviceRegistryExampleOptions { String commandData = "Specify with --data"; String configuration = "Specify with -configuration"; String deviceId; // Default to UUID? + String gatewayId; String pubsubTopic; String registryName; String member; @@ -122,6 +123,13 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { .hasArg() .desc("Name for your Device.") .build()); + options.addOption( + Option.builder() + .type(String.class) + .longOpt("gateway_id") + .hasArg() + .desc("Name for your Device.") + .build()); options.addOption( Option.builder() .type(String.class) @@ -180,6 +188,10 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { res.deviceId = commandLine.getOptionValue("device_id"); } + if (commandLine.hasOption("device_id")) { + res.gatewayId = commandLine.getOptionValue("gateway_id"); + } + if (commandLine.hasOption("project_id")) { res.projectId = commandLine.getOptionValue("project_id"); } else { @@ -211,6 +223,9 @@ public static DeviceRegistryExampleOptions fromFlags(String[] args) { if (commandLine.hasOption("device_id")) { res.deviceId = commandLine.getOptionValue("device_id"); } + if (commandLine.hasOption("gateway_id")) { + res.gatewayId = commandLine.getOptionValue("gateway_id"); + } if (commandLine.hasOption("configuration")) { res.configuration = commandLine.getOptionValue("configuration"); } diff --git a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java index fb35a5db9b9..d6108409c0e 100644 --- a/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java +++ b/iot/api-client/manager/src/main/java/com/example/cloud/iot/examples/MqttExample.java @@ -17,6 +17,7 @@ package com.example.cloud.iot.examples; // [START iot_mqtt_includes] + import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @@ -254,9 +255,9 @@ public static void sendDataFromBoundDevice( gatewayId, privateKeyFile, algorithm); - DeviceRegistryExample.attachDeviceToGateway(client, deviceId); + attachDeviceToGateway(client, deviceId); sendDataFromDevice(client, deviceId, messageType, telemetryData); - DeviceRegistryExample.detachDeviceFromGateway(client, deviceId); + detachDeviceFromGateway(client, deviceId); // [END send_data_from_bound_device] } @@ -284,10 +285,35 @@ public static void listenForConfigMessages( privateKeyFile, algorithm); // Connect the bound device and listen for configuration messages. - DeviceRegistryExample.attachDeviceToGateway(client, deviceId); + attachDeviceToGateway(client, deviceId); attachCallback(client, deviceId); - DeviceRegistryExample.detachDeviceFromGateway(client, deviceId); + detachDeviceFromGateway(client, deviceId); + } + + public static void attachDeviceToGateway(MqttClient client, String deviceId) + throws MqttException { + // [START iot_attach_device] + final String attachTopic = String.format("/devices/%s/attach", deviceId); + System.out.println(String.format("Attaching: %s", attachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(attachTopic, message); + // [END iot_attach_device] + } + + /** Detaches a bound device from the Gateway. */ + public static void detachDeviceFromGateway(MqttClient client, String deviceId) + throws MqttException { + // [START iot_detach_device] + final String detachTopic = String.format("/devices/%s/detach", deviceId); + System.out.println(String.format("Detaching: %s", detachTopic)); + String attachPayload = "{}"; + MqttMessage message = new MqttMessage(attachPayload.getBytes()); + message.setQos(1); + client.publish(detachTopic, message); + // [END iot_detach_device] } public static void mqttDeviceDemo(MqttExampleOptions options) diff --git a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java index 93e459eda40..de66507c3d8 100644 --- a/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java +++ b/iot/api-client/manager/src/test/java/com/example/cloud/iot/examples/ManagerIT.java @@ -615,7 +615,7 @@ public void testErrorTopic() throws Exception { new Thread() { public void run() { try { - DeviceRegistryExample.attachDeviceToGateway(client, "garbage-device"); + MqttExample.attachDeviceToGateway(client, "garbage-device"); MqttExample.attachCallback(client, "garbage-device"); } catch (Exception e) { // TODO: Fail diff --git a/jobs/v2/pom.xml b/jobs/v2/pom.xml index fb53a0f6f34..533c6b5c31d 100644 --- a/jobs/v2/pom.xml +++ b/jobs/v2/pom.xml @@ -15,7 +15,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/jobs/v3/pom.xml b/jobs/v3/pom.xml index 80a5a148b63..dfbf057ade1 100644 --- a/jobs/v3/pom.xml +++ b/jobs/v3/pom.xml @@ -15,7 +15,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/kms/pom.xml b/kms/pom.xml index 08824bdfd5e..bd271bc5719 100644 --- a/kms/pom.xml +++ b/kms/pom.xml @@ -12,7 +12,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/language/analysis/pom.xml b/language/analysis/pom.xml index 67e15af4d91..14a6a5fc3f0 100644 --- a/language/analysis/pom.xml +++ b/language/analysis/pom.xml @@ -27,7 +27,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 @@ -78,7 +78,7 @@ limitations under the License. org.apache.maven.plugins maven-failsafe-plugin - 2.18.1 + 3.0.0-M3 diff --git a/language/automl/pom.xml b/language/automl/pom.xml index 5665a5b2a56..a64d7fdd18a 100644 --- a/language/automl/pom.xml +++ b/language/automl/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/language/cloud-client/pom.xml b/language/cloud-client/pom.xml index 91531e9a003..94dba3da2b9 100644 --- a/language/cloud-client/pom.xml +++ b/language/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 1.8 diff --git a/logging/cloud-client/pom.xml b/logging/cloud-client/pom.xml index 78207415295..671c8847734 100644 --- a/logging/cloud-client/pom.xml +++ b/logging/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 @@ -63,7 +63,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.18.1 + 3.0.0-M3 ${project.build.outputDirectory} 3 diff --git a/logging/jul/pom.xml b/logging/jul/pom.xml index cde875e0440..71a56d2f141 100644 --- a/logging/jul/pom.xml +++ b/logging/jul/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/logging/logback/pom.xml b/logging/logback/pom.xml index e5caa336694..dd23afaa227 100644 --- a/logging/logback/pom.xml +++ b/logging/logback/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/logging/pom.xml b/logging/pom.xml deleted file mode 100644 index 0a45ba14c7d..00000000000 --- a/logging/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - 4.0.0 - com.google.cloud.logging.samples - cloud-logging-samples - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - 1.8 - 1.8 - - - - logback - jul - cloud-client - - - diff --git a/memorystore/redis/pom.xml b/memorystore/redis/pom.xml index bef71ee3da9..1ff2c0a0996 100644 --- a/memorystore/redis/pom.xml +++ b/memorystore/redis/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/mlengine/online-prediction/pom.xml b/mlengine/online-prediction/pom.xml index 318a898a587..1004a21cf9c 100644 --- a/mlengine/online-prediction/pom.xml +++ b/mlengine/online-prediction/pom.xml @@ -24,7 +24,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/monitoring/cloud-client/pom.xml b/monitoring/cloud-client/pom.xml index 366ec3b90d7..2abd0da7e61 100644 --- a/monitoring/cloud-client/pom.xml +++ b/monitoring/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/monitoring/v3/pom.xml b/monitoring/v3/pom.xml index 6cb2a0fb7f0..e75c5959220 100644 --- a/monitoring/v3/pom.xml +++ b/monitoring/v3/pom.xml @@ -27,7 +27,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/opencensus/pom.xml b/opencensus/pom.xml index ba75c01de61..35c957bafd1 100644 --- a/opencensus/pom.xml +++ b/opencensus/pom.xml @@ -29,7 +29,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/pom.xml b/pom.xml deleted file mode 100644 index d3b48f1e88a..00000000000 --- a/pom.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - 4.0.0 - 1.0.0 - com.google.cloud - doc-samples - pom - - - - com.google.cloud.samples - shared-configuration - 1.0.9 - - - - 1.8 - 1.8 - - - - - appengine - appengine-java8 - auth - flexible - - bigquery/cloud-client - bigquery/datatransfer/cloud-client - bigquery/rest - bigquery/bigquerystorage - - cdn/signed-urls - - cloud-sql/mysql/servlet - cloud-sql/postgres/servlet - - compute - container-registry/container-analysis - - dataflow/spanner-io - dataflow/transforms - - datalabeling/beta/cloud-client - - datastore - datastore/cloud-client - - dialogflow/cloud-client - - dlp - - errorreporting - - firestore - - iap - - kms - - language/analysis - language/cloud-client - - logging - - mlengine/online-prediction - - monitoring/cloud-client - monitoring/v3 - - memorystore/redis - - opencensus - - pubsub/cloud-client - - spanner/cloud-client - - speech/cloud-client - - storage/cloud-client - storage/json-api - storage/s3-sdk - storage/storage-transfer - storage/xml-api/cmdline-sample - storage/xml-api/serviceaccount-appengine-sample - - texttospeech/cloud-client - - translate/cloud-client - - unittests - video/beta - video/cloud-client - vision/beta/cloud-client - vision/cloud-client - vision/face-detection - vision/label - vision/landmark-detection - vision/text - - - diff --git a/pubsub/cloud-client/pom.xml b/pubsub/cloud-client/pom.xml index ed5391bb700..42cdc490089 100644 --- a/pubsub/cloud-client/pom.xml +++ b/pubsub/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/spanner/cloud-client/pom.xml b/spanner/cloud-client/pom.xml index 0f2f7940a4e..733c0ad27a8 100644 --- a/spanner/cloud-client/pom.xml +++ b/spanner/cloud-client/pom.xml @@ -26,7 +26,7 @@ limitations under the License. com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 @@ -140,6 +140,7 @@ limitations under the License.
+ spanner-google-cloud-samples maven-assembly-plugin @@ -167,7 +168,7 @@ limitations under the License. org.apache.maven.plugins maven-failsafe-plugin - 2.19.1 + 3.0.0-M3 default-instance diff --git a/spanner/cloud-client/src/main/java/com/example/spanner/SpannerSample.java b/spanner/cloud-client/src/main/java/com/example/spanner/SpannerSample.java index 5bfe9e082b3..980ef61c723 100644 --- a/spanner/cloud-client/src/main/java/com/example/spanner/SpannerSample.java +++ b/spanner/cloud-client/src/main/java/com/example/spanner/SpannerSample.java @@ -60,8 +60,8 @@ *
  • Writing data using a read-write transaction. *
  • Using an index to read and execute SQL queries over data. *
  • Using commit timestamp for tracking when a record was last updated. - *
  • Using Google API Extensions for Java to make thread-safe requests via - * long-running operations. http://googleapis.github.io/gax-java/ + *
  • Using Google API Extensions for Java to make thread-safe requests via long-running + * operations. http://googleapis.github.io/gax-java/ * */ public class SpannerSample { @@ -262,13 +262,13 @@ static void deleteExampleData(DatabaseClient dbClient) { // KeySet.singleKey() can be used to delete one row at a time. for (Singer singer : SINGERS) { mutations.add( - Mutation.delete("Singers", - KeySet.singleKey(Key.newBuilder().append(singer.singerId).build()))); + Mutation.delete( + "Singers", KeySet.singleKey(Key.newBuilder().append(singer.singerId).build()))); } dbClient.write(mutations); System.out.printf("Records deleted.\n"); - } + } // [END spanner_delete_data] // [START spanner_query_data] @@ -306,12 +306,11 @@ static void read(DatabaseClient dbClient) { // [START spanner_add_column] static void addMarketingBudget(DatabaseAdminClient adminClient, DatabaseId dbId) { OperationFuture op = - adminClient - .updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"), - null); + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("ALTER TABLE Albums ADD COLUMN MarketingBudget INT64"), + null); try { // Initiate the request which returns an OperationFuture. op.get(); @@ -372,12 +371,12 @@ public Void run(TransactionContext transaction) throws Exception { // Transaction will only be committed if this condition still holds at the time of // commit. Otherwise it will be aborted and the callable will be rerun by the // client library. - if (album2Budget >= 300000) { + long transfer = 200000; + if (album2Budget >= transfer) { long album1Budget = transaction .readRow("Albums", Key.of(1, 1), Arrays.asList("MarketingBudget")) .getLong(0); - long transfer = 200000; album1Budget += transfer; album2Budget -= transfer; transaction.buffer( @@ -428,12 +427,11 @@ static void queryMarketingBudget(DatabaseClient dbClient) { // [START spanner_create_index] static void addIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { OperationFuture op = - adminClient - .updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), - null); + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList("CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)"), + null); try { // Initiate the request which returns an OperationFuture. op.get(); @@ -499,14 +497,13 @@ static void readUsingIndex(DatabaseClient dbClient) { // [START spanner_create_storing_index] static void addStoringIndex(DatabaseAdminClient adminClient, DatabaseId dbId) { OperationFuture op = - adminClient - .updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " - + "STORING (MarketingBudget)"), - null); + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) " + + "STORING (MarketingBudget)"), + null); try { // Initiate the request which returns an OperationFuture. op.get(); @@ -589,14 +586,13 @@ static void readStaleData(DatabaseClient dbClient) { // [START spanner_add_timestamp_column] static void addCommitTimestamp(DatabaseAdminClient adminClient, DatabaseId dbId) { OperationFuture op = - adminClient - .updateDatabaseDdl( - dbId.getInstanceId().getInstance(), - dbId.getDatabase(), - Arrays.asList( - "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " - + "OPTIONS (allow_commit_timestamp=true)"), - null); + adminClient.updateDatabaseDdl( + dbId.getInstanceId().getInstance(), + dbId.getDatabase(), + Arrays.asList( + "ALTER TABLE Albums ADD COLUMN LastUpdateTime TIMESTAMP " + + "OPTIONS (allow_commit_timestamp=true)"), + null); try { // Initiate the request which returns an OperationFuture. op.get(); @@ -675,9 +671,7 @@ static void querySingersTable(DatabaseClient dbClient) { ResultSet resultSet = dbClient .singleUse() - .executeQuery( - Statement.of( - "SELECT SingerId, FirstName, LastName FROM Singers")); + .executeQuery(Statement.of("SELECT SingerId, FirstName, LastName FROM Singers")); while (resultSet.next()) { System.out.printf( "%s %s %s\n", @@ -1013,6 +1007,28 @@ public Void run(TransactionContext transaction) throws Exception { } // [END spanner_dml_getting_started_insert] + // [START spanner_query_with_parameter] + static void queryWithParameter(DatabaseClient dbClient) { + Statement statement = + Statement.newBuilder( + "SELECT SingerId, FirstName, LastName\n" + + "FROM Singers\n" + + "WHERE LastName = @lastName") + .bind("lastName") + .to("Garcia") + .build(); + + ResultSet resultSet = dbClient.singleUse().executeQuery(statement); + while (resultSet.next()) { + System.out.printf( + "%d %s %s\n", + resultSet.getLong("SingerId"), + resultSet.getString("FirstName"), + resultSet.getString("LastName")); + } + } + // [END spanner_query_with_parameter] + // [START spanner_dml_getting_started_update] static void writeWithTransactionUsingDml(DatabaseClient dbClient) { dbClient @@ -1024,40 +1040,40 @@ public Void run(TransactionContext transaction) throws Exception { // Transfer marketing budget from one album to another. We do it in a transaction to // ensure that the transfer is atomic. String sql1 = - "SELECT MarketingBudget from Albums WHERE SingerId = 1 and AlbumId = 1"; + "SELECT MarketingBudget from Albums WHERE SingerId = 2 and AlbumId = 2"; ResultSet resultSet = transaction.executeQuery(Statement.of(sql1)); - long album1Budget = 0; + long album2Budget = 0; while (resultSet.next()) { - album1Budget = resultSet.getLong("MarketingBudget"); + album2Budget = resultSet.getLong("MarketingBudget"); } // Transaction will only be committed if this condition still holds at the time of // commit. Otherwise it will be aborted and the callable will be rerun by the // client library. - if (album1Budget >= 300000) { + long transfer = 200000; + if (album2Budget >= transfer) { String sql2 = - "SELECT MarketingBudget from Albums WHERE SingerId = 2 and AlbumId = 2"; + "SELECT MarketingBudget from Albums WHERE SingerId = 1 and AlbumId = 1"; ResultSet resultSet2 = transaction.executeQuery(Statement.of(sql2)); - long album2Budget = 0; - while (resultSet.next()) { - album2Budget = resultSet2.getLong("MarketingBudget"); + long album1Budget = 0; + while (resultSet2.next()) { + album1Budget = resultSet2.getLong("MarketingBudget"); } - long transfer = 200000; - album2Budget += transfer; - album1Budget -= transfer; + album1Budget += transfer; + album2Budget -= transfer; Statement updateStatement = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 1 and AlbumId = 1") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 1 and AlbumId = 1") .bind("AlbumBudget") .to(album1Budget) .build(); transaction.executeUpdate(updateStatement); Statement updateStatement2 = Statement.newBuilder( - "UPDATE Albums " - + "SET MarketingBudget = @AlbumBudget " - + "WHERE SingerId = 2 and AlbumId = 2") + "UPDATE Albums " + + "SET MarketingBudget = @AlbumBudget " + + "WHERE SingerId = 2 and AlbumId = 2") .bind("AlbumBudget") .to(album2Budget) .build(); @@ -1085,7 +1101,7 @@ static void deleteUsingPartitionedDml(DatabaseClient dbClient) { } // [END spanner_dml_partitioned_delete] - // [START spanner_dml_batch_update] + // [START spanner_dml_batch_update] static void updateUsingBatchDml(DatabaseClient dbClient) { dbClient .readWriteTransaction() @@ -1094,23 +1110,24 @@ static void updateUsingBatchDml(DatabaseClient dbClient) { @Override public Void run(TransactionContext transaction) throws Exception { List stmts = new ArrayList(); - String sql = "INSERT INTO Albums " - + "(SingerId, AlbumId, AlbumTitle, MarketingBudget) " - + "VALUES (1, 3, 'Test Album Title', 10000) "; + String sql = + "INSERT INTO Albums " + + "(SingerId, AlbumId, AlbumTitle, MarketingBudget) " + + "VALUES (1, 3, 'Test Album Title', 10000) "; stmts.add(Statement.of(sql)); - sql = "UPDATE Albums " + sql = + "UPDATE Albums " + "SET MarketingBudget = MarketingBudget * 2 " + "WHERE SingerId = 1 and AlbumId = 3"; stmts.add(Statement.of(sql)); - long [] rowCounts; + long[] rowCounts; try { rowCounts = transaction.batchUpdate(stmts); } catch (SpannerBatchUpdateException e) { rowCounts = e.getUpdateCounts(); } for (int i = 0; i < rowCounts.length; i++) { - System.out.printf( - "%d record updated by stmt %d.\n", rowCounts[i], i); + System.out.printf("%d record updated by stmt %d.\n", rowCounts[i], i); } return null; } @@ -1229,6 +1246,9 @@ static void run( case "writeusingdml": writeUsingDml(dbClient); break; + case "querywithparameter": + queryWithParameter(dbClient); + break; case "writewithtransactionusingdml": writeWithTransactionUsingDml(dbClient); break; @@ -1272,7 +1292,7 @@ static void printUsageAndExit() { System.err.println(" SpannerExample querywithtimestamp my-instance example-db"); System.err.println(" SpannerExample createtablewithtimestamp my-instance example-db"); System.err.println(" SpannerExample writewithtimestamp my-instance example-db"); - System.err.println(" SpannerExample querysingerstable my-instance example-db"); + System.err.println(" SpannerExample querysingerstable my-instance example-db"); System.err.println(" SpannerExample queryperformancestable my-instance example-db"); System.err.println(" SpannerExample writestructdata my-instance example-db"); System.err.println(" SpannerExample querywithstruct my-instance example-db"); @@ -1286,6 +1306,7 @@ static void printUsageAndExit() { System.err.println(" SpannerExample writeandreadusingdml my-instance example-db"); System.err.println(" SpannerExample updateusingdmlwithstruct my-instance example-db"); System.err.println(" SpannerExample writeusingdml my-instance example-db"); + System.err.println(" SpannerExample queryWithParameter my-instance example-db"); System.err.println(" SpannerExample writewithtransactionusingdml my-instance example-db"); System.err.println(" SpannerExample updateusingpartitioneddml my-instance example-db"); System.err.println(" SpannerExample deleteusingpartitioneddml my-instance example-db"); diff --git a/spanner/cloud-client/src/test/java/com/example/spanner/SpannerSampleIT.java b/spanner/cloud-client/src/test/java/com/example/spanner/SpannerSampleIT.java index b20262fc9d9..680eb3cdc92 100644 --- a/spanner/cloud-client/src/test/java/com/example/spanner/SpannerSampleIT.java +++ b/spanner/cloud-client/src/test/java/com/example/spanner/SpannerSampleIT.java @@ -22,7 +22,6 @@ import com.google.cloud.spanner.DatabaseId; import com.google.cloud.spanner.Spanner; import com.google.cloud.spanner.SpannerOptions; - import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.UUID; @@ -32,9 +31,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -/** - * Unit tests for {@code SpannerSample} - */ +/** Unit tests for {@code SpannerSample} */ @RunWith(JUnit4.class) @SuppressWarnings("checkstyle:abbreviationaswordinname") public class SpannerSampleIT { @@ -50,7 +47,7 @@ private String runSample(String command) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); PrintStream out = new PrintStream(bout); System.setOut(out); - SpannerSample.main(new String[]{command, instanceId, databaseId}); + SpannerSample.main(new String[] {command, instanceId, databaseId}); System.setOut(stdOut); return bout.toString(); } @@ -144,7 +141,7 @@ public void testSample() throws Exception { assertThat(out).startsWith("6\n"); out = runSample("querywitharrayofstruct"); - assertThat(out).startsWith("6\n7"); + assertThat(out).startsWith("8\n7\n6"); out = runSample("querystructfield"); assertThat(out).startsWith("6\n"); @@ -181,15 +178,17 @@ public void testSample() throws Exception { assertThat(out).contains("Russell Morales"); assertThat(out).contains("Jacqueline Long"); assertThat(out).contains("Dylan Shaw"); + out = runSample("querywithparameter"); + assertThat(out).contains("12 Melissa Garcia"); runSample("writewithtransactionusingdml"); - out = runSample("querymarketingbudget"); - assertThat(out).contains("1 1 1800000"); - assertThat(out).contains("2 2 200000"); - + out = runSample("querymarketingbudget"); + assertThat(out).contains("1 1 2200000"); + assertThat(out).contains("2 2 550000"); + runSample("updateusingpartitioneddml"); out = runSample("querymarketingbudget"); - assertThat(out).contains("1 1 1800000"); + assertThat(out).contains("1 1 2200000"); assertThat(out).contains("2 2 100000"); runSample("deleteusingpartitioneddml"); diff --git a/spanner/leaderboard/complete/pom.xml b/spanner/leaderboard/complete/pom.xml index 29bb4dd568c..503df5f010f 100644 --- a/spanner/leaderboard/complete/pom.xml +++ b/spanner/leaderboard/complete/pom.xml @@ -25,7 +25,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/spanner/leaderboard/step4/pom.xml b/spanner/leaderboard/step4/pom.xml index d8daee79ee8..86735f0fb57 100644 --- a/spanner/leaderboard/step4/pom.xml +++ b/spanner/leaderboard/step4/pom.xml @@ -14,8 +14,8 @@ UTF-8 - 1.7 - 1.7 + 1.8 + 1.8 + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.task + tasks-samples + + + + com.google.cloud.samples + shared-configuration + 1.0.11 + + + + + 1.8 + 1.8 + false + + + + + + com.google.cloud + google-cloud-tasks + 0.88.0-beta + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.4.0 + + + HttpTask + + java + + + com.example.task.CreateHttpTask + false + + + + WithToken + + java + + + com.example.task.CreateHttpTaskWithToken + false + + + + + + + diff --git a/tasks/src/main/java/com/example/task/CreateHttpTask.java b/tasks/src/main/java/com/example/task/CreateHttpTask.java new file mode 100644 index 00000000000..6e8412426bb --- /dev/null +++ b/tasks/src/main/java/com/example/task/CreateHttpTask.java @@ -0,0 +1,64 @@ +/* + * Copyright 2018 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.task; + +// [START cloud_tasks_create_http_task] +import com.google.cloud.tasks.v2beta3.CloudTasksClient; +import com.google.cloud.tasks.v2beta3.HttpMethod; +import com.google.cloud.tasks.v2beta3.HttpRequest; +import com.google.cloud.tasks.v2beta3.QueueName; +import com.google.cloud.tasks.v2beta3.Task; +import com.google.protobuf.ByteString; +import java.nio.charset.Charset; + +public class CreateHttpTask { + + public static void main(String[] args) throws Exception { + String projectId = System.getenv("PROJECT_ID"); + String queueName = System.getenv("QUEUE_ID"); + String location = System.getenv("LOCATION_ID"); + String url = System.getenv("URL"); + + // Instantiates a client. + try (CloudTasksClient client = CloudTasksClient.create()) { + // Variables provided by the system variables. + // projectId = "my-project-id"; + // queueName = "my-queue"; + // location = "us-central1"; + // url = "https://example.com/taskhandler"; + String payload = "hello"; + + // Construct the fully qualified queue name. + String queuePath = QueueName.of(projectId, location, queueName).toString(); + + // Construct the task body. + Task.Builder taskBuilder = + Task.newBuilder() + .setHttpRequest( + HttpRequest.newBuilder() + .setBody(ByteString.copyFrom(payload, Charset.defaultCharset())) + .setUrl(url) + .setHttpMethod(HttpMethod.POST) + .build()); + + // Send create task request. + Task task = client.createTask(queuePath, taskBuilder.build()); + System.out.println("Task created: " + task.getName()); + } + } +} +// [END cloud_tasks_create_http_task] diff --git a/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java new file mode 100644 index 00000000000..f67cee97d32 --- /dev/null +++ b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java @@ -0,0 +1,71 @@ +/* + * Copyright 2019 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.task; + +// [START cloud_tasks_create_http_task_with_token] +import com.google.cloud.tasks.v2beta3.CloudTasksClient; +import com.google.cloud.tasks.v2beta3.HttpMethod; +import com.google.cloud.tasks.v2beta3.HttpRequest; +import com.google.cloud.tasks.v2beta3.OidcToken; +import com.google.cloud.tasks.v2beta3.QueueName; +import com.google.cloud.tasks.v2beta3.Task; +import com.google.protobuf.ByteString; +import java.nio.charset.Charset; + +public class CreateHttpTaskWithToken { + + public static void main(String[] args) throws Exception { + String projectId = System.getenv("PROJECT_ID"); + String queueName = System.getenv("QUEUE_ID"); + String location = System.getenv("LOCATION_ID"); + String url = System.getenv("URL"); + + // Instantiates a client. + try (CloudTasksClient client = CloudTasksClient.create()) { + // Variables provided by the system variables. + // projectId = "my-project-id"; + // queueName = "my-queue"; + // location = "us-central1"; + // url = "https://example.com/taskhandler"; + String payload = "hello"; + + // Construct the fully qualified queue name. + String queuePath = QueueName.of(projectId, location, queueName).toString(); + + // Add your service account email to construct the OIDC token. + // in order to add an authentication header to the request. + OidcToken.Builder oidcTokenBuilder = + OidcToken.newBuilder().setServiceAccountEmail(""); + + // Construct the task body. + Task.Builder taskBuilder = + Task.newBuilder() + .setHttpRequest( + HttpRequest.newBuilder() + .setBody(ByteString.copyFrom(payload, Charset.defaultCharset())) + .setHttpMethod(HttpMethod.POST) + .setUrl(url) + .setOidcToken(oidcTokenBuilder) + .build()); + + // Send create task request. + Task task = client.createTask(queuePath, taskBuilder.build()); + System.out.println("Task created: " + task.getName()); + } + } +} +// [END cloud_tasks_create_http_task_with_token] diff --git a/texttospeech/beta/pom.xml b/texttospeech/beta/pom.xml index 2c54a15ce45..613e2465d0c 100644 --- a/texttospeech/beta/pom.xml +++ b/texttospeech/beta/pom.xml @@ -16,12 +16,14 @@ tts-samples jar - + - doc-samples - com.google.cloud - 1.0.0 - ../.. + com.google.cloud.samples + shared-configuration + 1.0.11 diff --git a/texttospeech/cloud-client/pom.xml b/texttospeech/cloud-client/pom.xml index 11c941dfa64..dc6f7af54eb 100644 --- a/texttospeech/cloud-client/pom.xml +++ b/texttospeech/cloud-client/pom.xml @@ -16,12 +16,14 @@ tts-samples jar - + - doc-samples - com.google.cloud - 1.0.0 - ../.. + com.google.cloud.samples + shared-configuration + 1.0.11 diff --git a/trace/pom.xml b/trace/pom.xml index b67d6662f5e..9a9adabd2ab 100644 --- a/trace/pom.xml +++ b/trace/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/translate/automl/pom.xml b/translate/automl/pom.xml index 3ac92fb2c6e..221014744c8 100644 --- a/translate/automl/pom.xml +++ b/translate/automl/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/translate/cloud-client/pom.xml b/translate/cloud-client/pom.xml index cd2b184220c..817680d931e 100644 --- a/translate/cloud-client/pom.xml +++ b/translate/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/unittests/pom.xml b/unittests/pom.xml index 9780a999d74..1004b24ad5e 100644 --- a/unittests/pom.xml +++ b/unittests/pom.xml @@ -14,7 +14,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/video/beta/pom.xml b/video/beta/pom.xml index d6e949ea56c..3d76d439abc 100644 --- a/video/beta/pom.xml +++ b/video/beta/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/video/cloud-client/pom.xml b/video/cloud-client/pom.xml index b2a9cec1c68..71f6664f9de 100644 --- a/video/cloud-client/pom.xml +++ b/video/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/vision/automl/pom.xml b/vision/automl/pom.xml index 97e0b0ec8ec..a59fe41c026 100644 --- a/vision/automl/pom.xml +++ b/vision/automl/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/vision/beta/cloud-client/pom.xml b/vision/beta/cloud-client/pom.xml index b0e0f3decad..4e6539d7a43 100644 --- a/vision/beta/cloud-client/pom.xml +++ b/vision/beta/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/vision/cloud-client/pom.xml b/vision/cloud-client/pom.xml index 8307e648627..5009fa80dba 100644 --- a/vision/cloud-client/pom.xml +++ b/vision/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/vision/face-detection/pom.xml b/vision/face-detection/pom.xml index df09c3c50d9..4a0e2b3f389 100644 --- a/vision/face-detection/pom.xml +++ b/vision/face-detection/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/vision/label/pom.xml b/vision/label/pom.xml index 59b9976859b..b25badf61a2 100644 --- a/vision/label/pom.xml +++ b/vision/label/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/vision/landmark-detection/pom.xml b/vision/landmark-detection/pom.xml index 1c72d1b2f1e..7b5dcda6f69 100644 --- a/vision/landmark-detection/pom.xml +++ b/vision/landmark-detection/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11 diff --git a/vision/product-search/cloud-client/pom.xml b/vision/product-search/cloud-client/pom.xml index d9e8353748a..ac4a7d15392 100644 --- a/vision/product-search/cloud-client/pom.xml +++ b/vision/product-search/cloud-client/pom.xml @@ -26,7 +26,7 @@ com.google.cloud.samples shared-configuration - 1.0.10 + 1.0.11 diff --git a/vision/text/pom.xml b/vision/text/pom.xml index 9edd6513b51..f48ed80a77f 100644 --- a/vision/text/pom.xml +++ b/vision/text/pom.xml @@ -28,7 +28,7 @@ com.google.cloud.samples shared-configuration - 1.0.9 + 1.0.11