From df8ea9af7a21166a5fd3d27d2f4fb61243f6dcab Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 19 Apr 2019 12:20:36 -0700 Subject: [PATCH 01/49] [Cloud Tasks] Add HTTP push queue sample (#1355) * Add HTTP sample * Fix linting * remove CLI * Move http sample * Fix pom.xml * Update pom and linting * Update tasks version --- appengine-java8/tasks/README.md | 5 +- appengine-java8/tasks/pom.xml | 2 +- .../java/com/example/task/CreateTask.java | 4 +- .../java/com/example/task/TaskServlet.java | 2 +- tasks/README.md | 85 +++++++++++++++++++ tasks/pom.xml | 64 ++++++++++++++ .../java/com/example/task/CreateHttpTask.java | 64 ++++++++++++++ 7 files changed, 221 insertions(+), 5 deletions(-) create mode 100644 tasks/README.md create mode 100644 tasks/pom.xml create mode 100644 tasks/src/main/java/com/example/task/CreateHttpTask.java 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..ba427ae32bb 100644 --- a/appengine-java8/tasks/pom.xml +++ b/appengine-java8/tasks/pom.xml @@ -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/tasks/README.md b/tasks/README.md new file mode 100644 index 00000000000..760a0ba6605 --- /dev/null +++ b/tasks/README.md @@ -0,0 +1,85 @@ +# 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. + +`TaskServlet.java` 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-app-engine-queue 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) + +``` +mvn appengine:deploy +``` + +## Run the Sample Using the Command Line + +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= +``` + +### Using HTTP Push Queues + +Set an environment variable for the endpoint to your task handler. This is an +example url to send requests to the App Engine task handler: +``` +export URL=https://${PROJECT_ID}.appspot.com/tasks/create +``` + +Running the sample will create a task and send the task to the specific URL +endpoint, with a payload specified: + +``` +mvn exec:java -Dexec.mainClass="com.example.task.CreateHttpTask" +``` diff --git a/tasks/pom.xml b/tasks/pom.xml new file mode 100644 index 00000000000..5151ee378c0 --- /dev/null +++ b/tasks/pom.xml @@ -0,0 +1,64 @@ + + + + 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 + + com.example.task.CreateHttpTask + 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..9b4a1ac23d6 --- /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-appengine-queue"; + // location = "us-central1"; + // url = "https://.appspot.com/tasks/create"; + 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] From f8d02b4914fce846a2d99484a1487ce93accc856 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Fri, 19 Apr 2019 15:51:32 -0700 Subject: [PATCH 02/49] Misc testing fixes. (#1388) * Improve readability of test runner. * Fix Java versions in POMs. * Remove module check and silence only-changed skip. * Remove diff tests. * Work around for allowed enviroment variables. * Fix pathing mistake. * Pathing fix 2. * Remove skip-tests debug. * Update shared-config for all projects. * Fix missing parents. * Fix for missing diff tests. * debugging. * Fix diff check. * Misc testing fixes. --- .kokoro/java11/presubmit.cfg | 2 +- .kokoro/java8/presubmit.cfg | 2 +- .kokoro/tests/diff_tests.sh | 89 ---------- .kokoro/tests/run_diff_only.sh | 16 ++ .kokoro/tests/run_tests.sh | 162 +++++++++++------- appengine-java8/analytics/pom.xml | 2 +- appengine-java8/appidentity/pom.xml | 2 +- appengine-java8/bigquery/pom.xml | 2 +- appengine-java8/bigtable/pom.xml | 4 +- appengine-java8/cloudsql-postgres/pom.xml | 2 +- appengine-java8/cloudsql/pom.xml | 2 +- .../datastore-indexes-exploding/pom.xml | 2 +- .../datastore-indexes-perfect/pom.xml | 2 +- appengine-java8/datastore-indexes/pom.xml | 2 +- .../datastore-schedule-export/pom.xml | 2 +- appengine-java8/datastore/pom.xml | 2 +- appengine-java8/endpoints-v2-backend/pom.xml | 2 +- appengine-java8/endpoints-v2-guice/pom.xml | 2 +- .../endpoints-v2-migration/pom.xml | 2 +- appengine-java8/endpoints-v2-skeleton/pom.xml | 2 +- appengine-java8/firebase-event-proxy/pom.xml | 2 +- .../FirebaseEventProxy.java | 6 +- appengine-java8/firebase-tictactoe/pom.xml | 2 +- appengine-java8/gaeinfo/pom.xml | 2 +- .../guestbook-cloud-datastore/pom.xml | 2 +- appengine-java8/guestbook-objectify/pom.xml | 2 +- appengine-java8/images/pom.xml | 2 +- appengine-java8/mail/pom.xml | 2 +- appengine-java8/mailgun/pom.xml | 2 +- .../appengine/mailgun/MailgunServlet.java | 4 +- appengine-java8/mailjet/pom.xml | 2 +- appengine-java8/memcache/pom.xml | 2 +- appengine-java8/metadata/pom.xml | 2 +- appengine-java8/multitenancy/pom.xml | 2 +- appengine-java8/oauth2/pom.xml | 2 +- appengine-java8/pom.xml | 84 --------- appengine-java8/pubsub/pom.xml | 2 +- appengine-java8/remote-client/pom.xml | 2 +- appengine-java8/remote-server/pom.xml | 2 +- appengine-java8/requests/pom.xml | 2 +- appengine-java8/search/pom.xml | 2 +- appengine-java8/sendgrid/pom.xml | 2 +- appengine-java8/spanner/pom.xml | 2 +- appengine-java8/static-files/pom.xml | 2 +- appengine-java8/taskqueues-deferred/pom.xml | 2 +- appengine-java8/taskqueues-pull/pom.xml | 2 +- appengine-java8/taskqueues-push/pom.xml | 2 +- appengine-java8/tasks/pom.xml | 2 +- appengine-java8/translate-pubsub/pom.xml | 2 +- appengine-java8/twilio/pom.xml | 2 +- appengine-java8/urlfetch/pom.xml | 2 +- appengine-java8/users/pom.xml | 2 +- appengine-java8/websocket-jsr356/pom.xml | 2 +- appengine/analytics/pom.xml | 6 +- appengine/appidentity/pom.xml | 6 +- appengine/cloudsql/pom.xml | 6 +- appengine/datastore/indexes-exploding/pom.xml | 6 +- appengine/datastore/indexes-perfect/pom.xml | 6 +- appengine/datastore/indexes/pom.xml | 6 +- appengine/datastore/pom.xml | 43 ----- .../endpoints-frameworks-v2/backend/pom.xml | 6 +- .../guice-example/pom.xml | 6 +- .../migration-example/pom.xml | 6 +- appengine/endpoints-v1-helloworld/pom.xml | 6 +- .../gae-firebase-event-proxy/pom.xml | 6 +- appengine/firebase-tictactoe/pom.xml | 6 +- appengine/gaeinfo/pom.xml | 6 +- appengine/guestbook-cloud-datastore/pom.xml | 6 +- appengine/guestbook-objectify/pom.xml | 6 +- appengine/helloworld-new-plugins/pom.xml | 6 +- appengine/helloworld/pom.xml | 8 +- appengine/iap/pom.xml | 8 +- appengine/images/pom.xml | 13 +- appengine/logs/pom.xml | 8 +- appengine/mail/pom.xml | 8 +- appengine/mailgun/pom.xml | 6 +- appengine/mailjet/pom.xml | 6 +- appengine/memcache/pom.xml | 7 +- appengine/multitenancy/pom.xml | 6 +- appengine/oauth2/pom.xml | 6 +- appengine/pom.xml | 79 --------- appengine/pusher-chat/pom.xml | 6 +- appengine/remote/remote-client/pom.xml | 6 +- appengine/remote/remote-server/pom.xml | 6 +- appengine/requests/pom.xml | 6 +- appengine/search/pom.xml | 8 +- appengine/sendgrid/pom.xml | 8 +- appengine/sockets/pom.xml | 6 +- appengine/static-files/pom.xml | 6 +- appengine/taskqueue/defer-samples/pom.xml | 6 +- appengine/taskqueue/pom.xml | 40 ----- appengine/taskqueue/pull-samples/pom.xml | 6 +- appengine/taskqueue/push-samples/pom.xml | 6 +- appengine/twilio/pom.xml | 6 +- appengine/urlfetch/pom.xml | 6 +- appengine/users/pom.xml | 8 +- asset/cloud-client/pom.xml | 2 +- auth/pom.xml | 2 +- bigquery/bigquerystorage/pom.xml | 2 +- bigquery/cloud-client/pom.xml | 2 +- bigquery/datatransfer/cloud-client/pom.xml | 2 +- bigquery/rest/pom.xml | 2 +- cdn/signed-urls/pom.xml | 2 +- cloud-sql/mysql/servlet/pom.xml | 2 +- cloud-sql/postgres/servlet/pom.xml | 2 +- compute/cmdline/pom.xml | 2 +- compute/error-reporting/pom.xml | 2 +- compute/mailjet/pom.xml | 3 +- compute/pom.xml | 40 ----- compute/sendgrid/pom.xml | 2 +- compute/signed-metadata/pom.xml | 2 +- container-registry/container-analysis/pom.xml | 2 +- dataflow/spanner-io/pom.xml | 4 +- dataflow/transforms/pom.xml | 2 +- datalabeling/beta/cloud-client/pom.xml | 2 +- datastore/cloud-client/pom.xml | 2 +- datastore/pom.xml | 2 +- dialogflow/cloud-client/pom.xml | 2 +- dlp/pom.xml | 2 +- endpoints/getting-started/clients/pom.xml | 2 +- endpoints/multiple-versions/pom.xml | 11 +- errorreporting/pom.xml | 2 +- firestore/pom.xml | 2 +- flexible/analytics/pom.xml | 2 +- flexible/async-rest/pom.xml | 2 +- flexible/cloud-tasks/pom.xml | 2 +- flexible/cloudsql/pom.xml | 2 +- flexible/cloudstorage/pom.xml | 2 +- flexible/cron/pom.xml | 2 +- flexible/datastore/pom.xml | 11 +- flexible/disk/pom.xml | 2 +- flexible/errorreporting/pom.xml | 2 +- flexible/extending-runtime/pom.xml | 2 +- flexible/gaeinfo/pom.xml | 2 +- flexible/helloworld/pom.xml | 2 +- flexible/mailgun/pom.xml | 2 +- flexible/mailjet/pom.xml | 2 +- flexible/memcache/pom.xml | 2 +- flexible/pom.xml | 60 ------- flexible/postgres/pom.xml | 2 +- flexible/pubsub/pom.xml | 2 +- flexible/sendgrid/pom.xml | 2 +- flexible/sparkjava/pom.xml | 2 +- flexible/static-files/pom.xml | 2 +- flexible/twilio/pom.xml | 2 +- iam/api-client/pom.xml | 2 +- iap/pom.xml | 2 +- iot/api-client/codelab/manager/pom.xml | 2 +- iot/api-client/end-to-end-example/pom.xml | 2 +- iot/api-client/manager/pom.xml | 3 +- jobs/v2/pom.xml | 2 +- jobs/v3/pom.xml | 2 +- kms/pom.xml | 2 +- language/analysis/pom.xml | 4 +- language/automl/pom.xml | 2 +- language/cloud-client/pom.xml | 2 +- logging/cloud-client/pom.xml | 4 +- logging/jul/pom.xml | 2 +- logging/logback/pom.xml | 2 +- logging/pom.xml | 44 ----- memorystore/redis/pom.xml | 2 +- mlengine/online-prediction/pom.xml | 2 +- monitoring/cloud-client/pom.xml | 2 +- monitoring/v3/pom.xml | 2 +- opencensus/pom.xml | 2 +- pom.xml | 120 ------------- pubsub/cloud-client/pom.xml | 2 +- spanner/cloud-client/pom.xml | 4 +- spanner/leaderboard/complete/pom.xml | 2 +- spanner/leaderboard/step4/pom.xml | 6 +- spanner/leaderboard/step5/pom.xml | 6 +- spanner/leaderboard/step6/pom.xml | 6 +- speech/beta/pom.xml | 2 +- speech/cloud-client/pom.xml | 2 +- storage/cloud-client/pom.xml | 2 +- storage/json-api/pom.xml | 2 +- storage/s3-sdk/pom.xml | 2 +- storage/storage-transfer/pom.xml | 2 +- storage/xml-api/cmdline-sample/pom.xml | 2 +- .../serviceaccount-appengine-sample/pom.xml | 6 +- texttospeech/beta/pom.xml | 12 +- texttospeech/cloud-client/pom.xml | 12 +- trace/pom.xml | 2 +- translate/automl/pom.xml | 2 +- translate/cloud-client/pom.xml | 2 +- unittests/pom.xml | 2 +- video/beta/pom.xml | 2 +- video/cloud-client/pom.xml | 2 +- vision/automl/pom.xml | 2 +- vision/beta/cloud-client/pom.xml | 2 +- vision/cloud-client/pom.xml | 2 +- vision/face-detection/pom.xml | 2 +- vision/label/pom.xml | 2 +- vision/landmark-detection/pom.xml | 2 +- vision/product-search/cloud-client/pom.xml | 2 +- vision/text/pom.xml | 2 +- 196 files changed, 463 insertions(+), 938 deletions(-) delete mode 100755 .kokoro/tests/diff_tests.sh create mode 100755 .kokoro/tests/run_diff_only.sh delete mode 100644 appengine-java8/pom.xml delete mode 100644 appengine/datastore/pom.xml delete mode 100644 appengine/pom.xml delete mode 100644 appengine/taskqueue/pom.xml delete mode 100644 compute/pom.xml delete mode 100644 flexible/pom.xml delete mode 100644 logging/pom.xml delete mode 100644 pom.xml 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..00eeed208a4 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -13,72 +13,118 @@ # 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" + # Activate service account + gcloud auth activate-service-account \ + --key-file="$GOOGLE_APPLICATION_CREDENTIALS" \ + --project="$GOOGLE_CLOUD_PROJECT" + + cd github/java-docs-samples +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/appengine-java8/analytics/pom.xml b/appengine-java8/analytics/pom.xml index 5c3796f083f..863002dded2 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 3b98fafb3e7..4471f668451 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 a11fe35c486..27170624ca2 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 cbe814e0866..763970e4961 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/cloudsql-postgres/pom.xml b/appengine-java8/cloudsql-postgres/pom.xml index ecf4ad33853..3e4c530f0a9 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 ae4bf4537d0..d8edda25b70 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 54355d03efc..c6859d2a2be 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 799a3b4cbf1..ea18e495f28 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 774f8d6e27f..8e3b7ea01ed 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/pom.xml b/appengine-java8/datastore/pom.xml index 25c5da6141b..87df743ecb5 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 55416696a20..a489251632d 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 e0f4f052724..c76dfd8f488 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 e0b4f649d48..144e0e1b141 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 49f2b4e8a8a..fcb35f17aaa 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 460e6a2bc78..8d422795662 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 fee8853c660..466d58be676 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 631b99fbb28..f526187a94c 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 92402d9e78e..77cffe94b53 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 035fa1db5ea..476bac11e72 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 98a54a0cfb1..02a1bad7806 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 d8ff9aac74a..01488a35c80 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 7f8a305f375..f6804c9853f 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 e76e964c539..53f351c2a82 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 8b7afec81a0..9dbf4ca0758 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 c5d9f347854..7645034f02f 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 44f7f3abdcc..6dd7e9100d1 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/pom.xml b/appengine-java8/pubsub/pom.xml index ea07c4f9b79..fc40186461e 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 diff --git a/appengine-java8/remote-client/pom.xml b/appengine-java8/remote-client/pom.xml index 9b7d992f83d..5447b4293d1 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 966ea5c035f..8e956285192 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 031ee2e3f29..ca28e0d7760 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 bab1856b65c..3600cede09f 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 c15b6a1e468..4cbee6cb69b 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 f7d957cf2fc..b2449fd9ad8 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 01ecef56d69..b47d2432fd9 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 062d36d8bcf..1c61fc1ea2e 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/pom.xml b/appengine-java8/tasks/pom.xml index ba427ae32bb..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 diff --git a/appengine-java8/translate-pubsub/pom.xml b/appengine-java8/translate-pubsub/pom.xml index 4d57cd34ace..9cadcdf3dfa 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/users/pom.xml b/appengine-java8/users/pom.xml index f7f70edd942..a3f80da50ec 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 f23747cbf3d..e032c48aca7 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 e6f7857fa51..df746dc8543 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 66e6c2f3d5a..a8840db878b 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 22d290655a8..b8978cb9a36 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 ce6b32a9db8..a4205e0a6f9 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 aad18bed780..be24f8dedd6 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 4495c278bc3..0541a12bf7c 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 aeacb588559..d6826ce8678 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 8b459a0e25a..06d83e7e2eb 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 d3985952c1d..8fa4c4180cb 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 eda0c44e483..56f6030863f 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 60ea4455981..f6128e4fcda 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 faf7aee8912..7c1bd4c6b92 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 af6807d4b68..ec0be0f487f 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 36b3d4f924a..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.71 - - diff --git a/appengine/oauth2/pom.xml b/appengine/oauth2/pom.xml index 177feca621c..c1582a12548 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 bc890f10379..6f1315167ae 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 7da3ac49e94..8e3d79d4c06 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 041febc2eb3..cae25b2a1e4 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 fa930823424..389444f30d4 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 f1949cac9b9..74f34f88c37 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 4d871d2e655..34a393d6f76 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 ea55f30b6b2..6fa024ac1b3 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 0f270fa26c9..1fafca19809 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 9609836d374..d1da90113d6 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 e11f9648b44..0cd9a7f22e2 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 e8296d53039..0ab38b6ddbb 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 f0c0d5c56bb..f277d04d2e2 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 df3d205599f..5ff2d19ed43 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 8e88f5c73ff..d1442bdfc7f 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 33403b858e6..71b26b043d4 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/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 93577db1aba..cb4bce9cd61 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 d1571fff1dd..e96bb4a6e8b 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 3f9b6f1ca2a..d11727636d1 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 c2d64158333..76159da4837 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 86c74b291c8..459258045cc 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 48cf8b4761d..cef691423b6 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/dataflow/spanner-io/pom.xml b/dataflow/spanner-io/pom.xml index abc725e31a3..ba3032f58b0 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 @@ -51,7 +51,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.19.1 + 3.0.0-M3 default-instance diff --git a/dataflow/transforms/pom.xml b/dataflow/transforms/pom.xml index 203a062ab5a..1a7af6dca99 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 129f38a01ea..5761ab07fb9 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 affda335ff2..6bef52de9c4 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 26c93c627c4..a5096b3166f 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/dialogflow/cloud-client/pom.xml b/dialogflow/cloud-client/pom.xml index 81c907ba3c1..4b955a1f5b4 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 diff --git a/dlp/pom.xml b/dlp/pom.xml index 654bfc88610..dc944897b33 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 7cc97a35d53..70d5f065d59 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 319941237c8..e4282911c75 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 diff --git a/flexible/analytics/pom.xml b/flexible/analytics/pom.xml index b739728d8df..b3fe70fe3d7 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 3779d9594a2..a98053751a9 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 9d3a13c5a89..fd96a7ae33c 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 f9d667744df..8def6bbcb95 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 e773c1aa983..5fb53963590 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 ddd27338bcc..7410b228bd8 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 2c06fe8ab49..24d1ebba8cf 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 e8b46412c0d..1675366e131 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 c07bccc5304..43b382c985f 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 ba9a51be049..2472489c4b1 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 b9fa16e943c..aa0b8dfdf22 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/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 0c8bd578fa6..42bba95d801 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/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/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 cdef2c6bd68..05746890762 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 a2a1581d8bd..c0377163655 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 9722f1aea03..c87776f0f63 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 64b9e76c797..19e28f040a6 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 be410a0afff..270b176bed8 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 e2a84c979c8..5746addacae 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 b6f7c8f112a..e6c34ddcd7a 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 79fc4924f18..f897f1c9e5b 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 15944c47ead..b7b9030dfa1 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 e2c63b0e766..ea99578e704 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 b81021b448c..934ed188e6b 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 44f5ba7f16a..0a72461b1da 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 a9c646f4445..04bb822df22 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 @@ -167,7 +167,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/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 + - 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 57b22865054..df51b289917 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 0e6edd88a3c..398f90d8bdd 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 b7789cfd12f..3ee932d40bf 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 bfc0c743887..8b348c38b38 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 ffaa3562d3f..b57c0a5f2d0 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 c3643869a0d..446338693db 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 84d9f7745b3..60e5079d892 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 3d0a27f7aed..9b7c763ca96 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 570930cb0fc..1aab4a7fefa 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 8195d5581f9..adb678701f0 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 9aa9568354c..5eebdb78e01 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 From 9c54442261f5f0d012d7cb11953fd1453c327a15 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Mon, 22 Apr 2019 09:34:01 -0700 Subject: [PATCH 03/49] [Cloud Tasks] Add task sample with auth token (#1389) * Add task sample with auth token * add parent to pom * Update comments --- tasks/README.md | 25 ++++--- tasks/pom.xml | 26 +++++-- .../example/task/CreateHttpTaskWithToken.java | 71 +++++++++++++++++++ 3 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java diff --git a/tasks/README.md b/tasks/README.md index 760a0ba6605..dd13bd1d576 100644 --- a/tasks/README.md +++ b/tasks/README.md @@ -7,12 +7,11 @@ 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. - -`TaskServlet.java` is the main App Engine app. This app serves as an endpoint to receive -App Engine task attempts. +`CreateHTTPTask.java` constructs a task with an HTTP target and pushes it +to your queue. +`CreateHTTPTask.java` constructs a task with an HTTP target and OIDC token and pushes it +to your queue. ## Initial Setup @@ -28,7 +27,7 @@ App Engine task attempts. To create a queue using the Cloud SDK, use the following gcloud command: ``` -gcloud beta tasks queues create-app-engine-queue my-appengine-queue +gcloud beta tasks queues create-app-engine-queue my-queue ``` Note: A newly created queue will route to the default App Engine service and @@ -56,7 +55,7 @@ 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 +export QUEUE_ID=my-queue ``` And finally the location ID, which can be discovered with @@ -81,5 +80,15 @@ Running the sample will create a task and send the task to the specific URL endpoint, with a payload specified: ``` -mvn exec:java -Dexec.mainClass="com.example.task.CreateHttpTask" +mvn exec:java@HttpTask" +``` + +### Using HTTP Targets with Authentication Headers + +In `CreateHttpTaskWithToken.java`, add your service account email in place of +`` to authenticate the OIDC token. + +Running the sample with command: +``` +mvn exec:java@WithToken" ``` diff --git a/tasks/pom.xml b/tasks/pom.xml index 5151ee378c0..697eb29e61d 100644 --- a/tasks/pom.xml +++ b/tasks/pom.xml @@ -54,10 +54,28 @@ Copyright 2018 Google LLC org.codehaus.mojo exec-maven-plugin 1.4.0 - - com.example.task.CreateHttpTask - false - + + + HttpTask + + java + + + com.example.task.CreateHttpTask + false + + + + WithToken + + java + + + com.example.task.CreateHttpTaskWithToken + false + + + 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..0891d899c85 --- /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-appengine-queue"; + // location = "us-central1"; + // url = "https://example.com/tasks/create"; + 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] From 42db9a65efad683600e2254cd8b84cda9658f893 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Mon, 22 Apr 2019 13:15:12 -0700 Subject: [PATCH 04/49] Add Springboot Hello World sample for Java 11 (#1391) * Springboot sample * Update comments * Update comments --- .../.mvn/wrapper/maven-wrapper.properties | 1 + .../springboot-helloworld/README.md | 22 ++ appengine-java11/springboot-helloworld/mvnw | 286 ++++++++++++++++++ .../springboot-helloworld/mvnw.cmd | 161 ++++++++++ .../springboot-helloworld/pom.xml | 93 ++++++ .../src/main/appengine/app.yaml | 4 + .../springboot/SpringbootApplication.java | 21 ++ .../src/main/resources/application.properties | 0 .../SpringbootApplicationTests.java | 17 ++ 9 files changed, 605 insertions(+) create mode 100644 appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties create mode 100644 appengine-java11/springboot-helloworld/README.md create mode 100755 appengine-java11/springboot-helloworld/mvnw create mode 100644 appengine-java11/springboot-helloworld/mvnw.cmd create mode 100644 appengine-java11/springboot-helloworld/pom.xml create mode 100644 appengine-java11/springboot-helloworld/src/main/appengine/app.yaml create mode 100644 appengine-java11/springboot-helloworld/src/main/java/com/example/appengine/springboot/SpringbootApplication.java create mode 100644 appengine-java11/springboot-helloworld/src/main/resources/application.properties create mode 100644 appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java diff --git a/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties b/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 00000000000..71793467167 --- /dev/null +++ b/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip diff --git a/appengine-java11/springboot-helloworld/README.md b/appengine-java11/springboot-helloworld/README.md new file mode 100644 index 00000000000..bceaec89747 --- /dev/null +++ b/appengine-java11/springboot-helloworld/README.md @@ -0,0 +1,22 @@ +# Spring Boot Application Google App Engine Standard with Java 11 + +This sample shows how to deploy a Spring Boot application with an exploded fatjar +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). + +## Deploying + +```bash + mvn clean package appengine:deploy -Dapp.deploy.projectId= +``` + +To view your app, use command: +``` +gcloud app browse +``` +Or navigate to http://.appspot.com URL. diff --git a/appengine-java11/springboot-helloworld/mvnw b/appengine-java11/springboot-helloworld/mvnw new file mode 100755 index 00000000000..5551fde8e7d --- /dev/null +++ b/appengine-java11/springboot-helloworld/mvnw @@ -0,0 +1,286 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + wget "$jarUrl" -O "$wrapperJarPath" + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + curl -o "$wrapperJarPath" "$jarUrl" + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/appengine-java11/springboot-helloworld/mvnw.cmd b/appengine-java11/springboot-helloworld/mvnw.cmd new file mode 100644 index 00000000000..e5cfb0ae9ea --- /dev/null +++ b/appengine-java11/springboot-helloworld/mvnw.cmd @@ -0,0 +1,161 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" +FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + echo Found %WRAPPER_JAR% +) else ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" + echo Finished downloading %WRAPPER_JAR% +) +@REM End of extension + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml new file mode 100644 index 00000000000..aa9012d9038 --- /dev/null +++ b/appengine-java11/springboot-helloworld/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + com.example.appengine + springboot-helloworld-j11 + 0.0.1-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE + + + + + 11 + 11 + 11 + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.springframework.boot.experimental + spring-boot-thin-layout + 1.0.13.RELEASE + + + + + + + org.springframework.boot.experimental + spring-boot-thin-maven-plugin + 1.0.13.RELEASE + + ${project.build.directory}/appengine-staging + + + + resolve + + resolve + + false + + + + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0-rc5 + + 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..b5120153d4a --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml @@ -0,0 +1,4 @@ +runtime: java11 +instance_class: F2 +# The entrypoint here is mandatory as the appengine-staging area contains an exploded fatjar +entrypoint: 'java -XX:MaxRAM=256m -XX:ActiveProcessorCount=2 -Xmx32m -Dthin.root=. -jar springboot-thin-j11-0.0.1-SNAPSHOT.jar' 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..100ccac8b82 --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/main/java/com/example/appengine/springboot/SpringbootApplication.java @@ -0,0 +1,21 @@ +package com.example.appengine.springboot; + +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!"; + } + +} 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..e69de29bb2d diff --git a/appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java b/appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java new file mode 100644 index 00000000000..0c29b826162 --- /dev/null +++ b/appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java @@ -0,0 +1,17 @@ +package com.example.appengine.springboot; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringbootApplicationTests { + + @Test + public void contextLoads() { + } + +} + From 4c37c62c3f91fbd2ab98029c0f379de982905b95 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Mon, 22 Apr 2019 13:20:27 -0700 Subject: [PATCH 05/49] Hello World samples for Java 11 (#1380) * simple hello world * Simple fat jar hello world * Reduce instance size * Add parent to pom.xml * Linting --- appengine-java11/hello-world/Main.java | 40 +++++++++++++++ appengine-java11/hello-world/README.md | 20 ++++++++ appengine-java11/hello-world/app.yaml | 2 + appengine-java11/http-server/README.md | 21 ++++++++ appengine-java11/http-server/pom.xml | 47 +++++++++++++++++ .../http-server/src/main/appengine/app.yaml | 2 + .../main/java/com/example/appengine/Main.java | 50 +++++++++++++++++++ 7 files changed, 182 insertions(+) create mode 100644 appengine-java11/hello-world/Main.java create mode 100644 appengine-java11/hello-world/README.md create mode 100644 appengine-java11/hello-world/app.yaml create mode 100644 appengine-java11/http-server/README.md create mode 100644 appengine-java11/http-server/pom.xml create mode 100644 appengine-java11/http-server/src/main/appengine/app.yaml create mode 100644 appengine-java11/http-server/src/main/java/com/example/appengine/Main.java diff --git a/appengine-java11/hello-world/Main.java b/appengine-java11/hello-world/Main.java new file mode 100644 index 00000000000..1f07a6e3fdb --- /dev/null +++ b/appengine-java11/hello-world/Main.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +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(); + } +} diff --git a/appengine-java11/hello-world/README.md b/appengine-java11/hello-world/README.md new file mode 100644 index 00000000000..d219f6a674d --- /dev/null +++ b/appengine-java11/hello-world/README.md @@ -0,0 +1,20 @@ +# Hello World App for 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 http://.appspot.com URL. diff --git a/appengine-java11/hello-world/app.yaml b/appengine-java11/hello-world/app.yaml new file mode 100644 index 00000000000..f142d2b4f06 --- /dev/null +++ b/appengine-java11/hello-world/app.yaml @@ -0,0 +1,2 @@ +runtime: java11 +entrypoint: java Main.java diff --git a/appengine-java11/http-server/README.md b/appengine-java11/http-server/README.md new file mode 100644 index 00000000000..c2ee758a48b --- /dev/null +++ b/appengine-java11/http-server/README.md @@ -0,0 +1,21 @@ +# Single Fat Jar Application 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 http://.appspot.com URL. diff --git a/appengine-java11/http-server/pom.xml b/appengine-java11/http-server/pom.xml new file mode 100644 index 00000000000..6cf4e97417d --- /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-rc5 + + 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..abfdc495a95 --- /dev/null +++ b/appengine-java11/http-server/src/main/appengine/app.yaml @@ -0,0 +1,2 @@ +runtime: java11 +# No need for an entrypoint with single fatjar with correct manifest class-path entry. 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..4f71ecce0d8 --- /dev/null +++ b/appengine-java11/http-server/src/main/java/com/example/appengine/Main.java @@ -0,0 +1,50 @@ +/* + * 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.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(); + } +} From f7ab04f1aaf3bda6daa40ef32fb6636d65d3e9c8 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 23 Apr 2019 11:57:58 -0700 Subject: [PATCH 06/49] Update task sample for java 11 (#1382) * update task sample for java 11 * remove region tags * Remove CLI and update readme * respond to PR comments * Update pom.xml * Update scopes * Remove systempath dependency * Update tasks sample to use spring boot handler * Don't fail on missing web.xml * Add configuration for missing web.xml * Update licenses and styling * checkstyle * Format pom * Update style --- appengine-java11/tasks-handler/Dockerfile | 23 ++++ appengine-java11/tasks-handler/README.md | 4 + appengine-java11/tasks-handler/pom.xml | 108 ++++++++++++++++++ .../tasks-handler/src/main/appengine/app.yaml | 16 +++ .../appengine/taskhandler/Application.java | 35 ++++++ .../taskhandler/TaskHandlerController.java | 41 +++++++ .../src/main/resources/application.properties | 13 +++ appengine-java11/tasks/README.md | 98 ++++++++++++++++ appengine-java11/tasks/pom.xml | 75 ++++++++++++ .../java/com/example/task/CreateTask.java | 65 +++++++++++ 10 files changed, 478 insertions(+) create mode 100644 appengine-java11/tasks-handler/Dockerfile create mode 100644 appengine-java11/tasks-handler/README.md create mode 100644 appengine-java11/tasks-handler/pom.xml create mode 100644 appengine-java11/tasks-handler/src/main/appengine/app.yaml create mode 100644 appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/Application.java create mode 100644 appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/TaskHandlerController.java create mode 100644 appengine-java11/tasks-handler/src/main/resources/application.properties create mode 100644 appengine-java11/tasks/README.md create mode 100644 appengine-java11/tasks/pom.xml create mode 100644 appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java 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..bf27d85aa3d --- /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-rc5 + + 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..d3fb864db15 --- /dev/null +++ b/appengine-java11/tasks-handler/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: F4 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..b93cfb6c665 --- /dev/null +++ b/appengine-java11/tasks-handler/src/main/java/com/example/appengine/taskhandler/TaskHandlerController.java @@ -0,0 +1,41 @@ +/* + * 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.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; + } +} 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..daacf062b4b --- /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-app-engine-queue 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..0498017f2a7 --- /dev/null +++ b/appengine-java11/tasks/pom.xml @@ -0,0 +1,75 @@ + + + + 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..4f9d29ac224 --- /dev/null +++ b/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.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.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()); + } + } +} From 663a40bb3f421c301759dff75f223a6c6ce19427 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 23 Apr 2019 14:45:18 -0700 Subject: [PATCH 07/49] Move Java11 samples (#1359) * Add simple jetty web server for other applications * biquery sample * gaeinfo sample * update bigquery war file name * cloudsql sample * Cloud Postgresql sample * update license * spanner sample * bigtable sample * Add directory readme and pom * Update gaeinfo sample resource copying * update pom files * Update sample not to use com.google.* * Update Readmes * remove region tags * Add parent back to pom.xml * linting * Update pom.xml * Update parent README * remove parent pom.xml * linting * Kokoro - add packaging for jetty server * Add check for java 11 install * Update name for test instance * Update parent config * comment out test * Update test name. * Fix null pointer. * Delete big table sample --- .kokoro/tests/run_tests.sh | 7 + appengine-java11/README.md | 61 +++ .../appengine-simple-jetty-main/pom.xml | 56 +++ .../appengine/demo/jettymain/Main.java | 63 +++ appengine-java11/gaeinfo/README.md | 57 +++ appengine-java11/gaeinfo/pom.xml | 136 ++++++ .../gaeinfo/src/main/appengine/app.yaml | 3 + .../appengine/standard/GaeInfoServlet.java | 179 +++++++ .../main/webapp/WEB-INF/templates/index.html | 84 ++++ appengine-java11/spanner/README.md | 60 +++ appengine-java11/spanner/pom.xml | 107 +++++ .../spanner/src/main/appengine/app.yaml | 5 + .../appengine/spanner/SpannerClient.java | 134 ++++++ .../appengine/spanner/SpannerTasks.java | 435 ++++++++++++++++++ .../spanner/SpannerTasksServlet.java | 76 +++ 15 files changed, 1463 insertions(+) create mode 100644 appengine-java11/README.md create mode 100644 appengine-java11/appengine-simple-jetty-main/pom.xml create mode 100644 appengine-java11/appengine-simple-jetty-main/src/main/java/com/example/appengine/demo/jettymain/Main.java create mode 100644 appengine-java11/gaeinfo/README.md create mode 100644 appengine-java11/gaeinfo/pom.xml create mode 100644 appengine-java11/gaeinfo/src/main/appengine/app.yaml create mode 100644 appengine-java11/gaeinfo/src/main/java/com/example/appengine/standard/GaeInfoServlet.java create mode 100644 appengine-java11/gaeinfo/src/main/webapp/WEB-INF/templates/index.html create mode 100644 appengine-java11/spanner/README.md create mode 100644 appengine-java11/spanner/pom.xml create mode 100644 appengine-java11/spanner/src/main/appengine/app.yaml create mode 100644 appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerClient.java create mode 100644 appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasks.java create mode 100644 appengine-java11/spanner/src/main/java/com/example/appengine/spanner/SpannerTasksServlet.java diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh index 00eeed208a4..4907bec58ae 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -64,6 +64,13 @@ if [[ "$SCRIPT_DEBUG" != "true" ]]; then 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 package + cd ../../ +fi + echo -e "\n******************** TESTING PROJECTS ********************" # Switch to 'fail at end' to allow all tests to complete before exiting. set +e diff --git a/appengine-java11/README.md b/appengine-java11/README.md new file mode 100644 index 00000000000..80588b0c969 --- /dev/null +++ b/appengine-java11/README.md @@ -0,0 +1,61 @@ +# 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/java/ + +## Prerequisites + +**Private Alpha** +To access the Java 11 Google App Engine standard runtime, you'll need to apply +to become part of the App Engine [Alpha program](https://docs.google.com/forms/d/e/1FAIpQLSf5uE5eknJjFEmcVBI6sMitBU0QQ1LX_J7VrA_OTQabo6EEEw/viewform). + + +### 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 +``` + +### appengine-simple-jetty-main + +[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. 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..269af4279b3 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/pom.xml @@ -0,0 +1,56 @@ + + + 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.14.v20181114 + + + org.eclipse.jetty + jetty-webapp + 9.4.14.v20181114 + jar + + + org.eclipse.jetty + jetty-util + 9.4.14.v20181114 + + + org.eclipse.jetty + jetty-annotations + 9.4.14.v20181114 + jar + + + + org.eclipse.jetty + apache-jsp + 9.4.14.v20181114 + + + 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..1b28f9c3520 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/src/main/java/com/example/appengine/demo/jettymain/Main.java @@ -0,0 +1,63 @@ +/* + * 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; + +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(); + } +} diff --git a/appengine-java11/gaeinfo/README.md b/appengine-java11/gaeinfo/README.md new file mode 100644 index 00000000000..e0b57079d31 --- /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 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 +``` + +## Setup you Google Cloud 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` + +## 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..8a717c5c189 --- /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.google.appengine.demo + simple-jetty-main + 1 + system + ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + + + + 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-rc5 + + 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..e0faea3ceff --- /dev/null +++ b/appengine-java11/gaeinfo/src/main/appengine/app.yaml @@ -0,0 +1,3 @@ +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..bbef75dbbbd --- /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/spanner/README.md b/appengine-java11/spanner/README.md new file mode 100644 index 00000000000..0d17ff9bddb --- /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 +- 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..69d7a68f4c4 --- /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.google.appengine.demo + simple-jetty-main + 1 + system + ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + + + + 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-rc5 + + 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..d40a811e1f8 --- /dev/null +++ b/appengine-java11/spanner/src/main/appengine/app.yaml @@ -0,0 +1,5 @@ +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); + } + } +} From 9f7d910ecfdc4611041dc55c5147afc778f87200 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 23 Apr 2019 15:27:21 -0700 Subject: [PATCH 08/49] Add guestbook sample for Java 11 (#1381) * Add guestbook sample * update parent pom.xml * draft * Add firestore * clean up * Firestore sample * Update pom * Update licenses and comments * Add path to dependency * Fix pom --- .../guestbook-cloud-firestore/README.md | 57 ++++++++++ .../guestbook-cloud-firestore/pom.xml | 107 ++++++++++++++++++ .../src/main/appengine/app.yaml | 16 +++ .../java/com/example/guestbook/Greeting.java | 94 +++++++++++++++ .../java/com/example/guestbook/Guestbook.java | 99 ++++++++++++++++ .../com/example/guestbook/Persistence.java | 42 +++++++ .../guestbook/SignGuestbookServlet.java | 46 ++++++++ .../src/main/webapp/WEB-INF/web.xml | 23 ++++ .../src/main/webapp/index.jsp | 106 +++++++++++++++++ 9 files changed, 590 insertions(+) create mode 100644 appengine-java11/guestbook-cloud-firestore/README.md create mode 100644 appengine-java11/guestbook-cloud-firestore/pom.xml create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Greeting.java create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Guestbook.java create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Persistence.java create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/SignGuestbookServlet.java create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/webapp/WEB-INF/web.xml create mode 100644 appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp diff --git a/appengine-java11/guestbook-cloud-firestore/README.md b/appengine-java11/guestbook-cloud-firestore/README.md new file mode 100644 index 00000000000..707cd0b771c --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/README.md @@ -0,0 +1,57 @@ +# 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 + +* 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 [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..d298d413be3 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -0,0 +1,107 @@ + + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.guestbook + guestbook-cloud-firestore + + + 11 + 11 + + + + + + + + com.google.appengine.demo + simple-jetty-main + 1 + system + ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + + + + 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-rc5 + + 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..6b273ebb12b --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/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 +entrypoint: 'java -cp * com.google.appengine.demo.jettymain.Main guestbook.war' 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..1df05955874 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Greeting.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 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; + +/** Greeting model. */ +@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() { + // 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); + } + + @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..dc816fa43f3 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Guestbook.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 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; + +/** Guestbook model. */ +@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); + + // Get Guestbook reference in the collection. + bookRef = getFirestore().collection("Guestbooks").document(this.book); + // Add Guestbook to collection. + bookRef.set(bookData); + } + + public DocumentReference getBookRef() { + return bookRef; + } + + /** Get greetings for the Guestbook */ + 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 InterruptedException) { + System.out.println("Nothing to query."); + } + + return greetings.build(); + } + + @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..48b974b4ed2 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/Persistence.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.guestbook; + +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +import java.util.concurrent.atomic.AtomicReference; + +/** Create a persistence connection to your Firestore instance. */ +public class Persistence { + + private static AtomicReference firestore = new AtomicReference<>(); + + @SuppressWarnings("JavadocMethod") + public static Firestore getFirestore() { + if (firestore.get() == null) { + // Authorized Firestore service + firestore.set( + FirestoreOptions.newBuilder().setProjectId("YOUR-PROJECT-ID").build().getService()); + } + + return firestore.get(); + } + + public static void setFirestore(Firestore firestore) { + Persistence.firestore.set(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..e1c843f2ac5 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/java/com/example/guestbook/SignGuestbookServlet.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; + +import java.io.IOException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.ServletException; +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); + } +} 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..a78995dacad --- /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..d87f284b537 --- /dev/null +++ b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp @@ -0,0 +1,106 @@ + + + + +<%@ 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 the correct Ancestor key + Guestbook theBook = new Guestbook(guestbookName); + + // Run an ancestor 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 --%> +
+
+
+
+ +

Write Your Greeting

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

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)}
+
+ <% + } + } + %> + + + From 9a11673ec1933a7347d4fe44e42ba3d8621cdc7a Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 23 Apr 2019 16:14:50 -0700 Subject: [PATCH 09/49] Add Oauth2 sample for Java 11 (#1383) * Add Oauth2 sample for Java 11 * Update comments * Update README with install instructionons * Update pom * remove systempath dependency * Add license and update path to dependency * Update name * Fix name * Fix license * Update dep * fix parent --- .kokoro/tests/run_tests.sh | 2 +- appengine-java11/gaeinfo/pom.xml | 5 +- .../guestbook-cloud-firestore/pom.xml | 5 +- .../src/main/appengine/app.yaml | 2 +- appengine-java11/oauth2/README.md | 59 ++++++++ appengine-java11/oauth2/pom.xml | 133 ++++++++++++++++++ .../oauth2/src/main/appengine/app.yaml | 21 +++ .../com/example/appengine/LogoutServlet.java | 34 +++++ .../Oauth2AuthorizationCodeServlet.java | 51 +++++++ .../appengine/Oauth2CallbackServlet.java | 77 ++++++++++ .../java/com/example/appengine/Utils.java | 104 ++++++++++++++ .../oauth2/src/main/webapp/WEB-INF/web.xml | 27 ++++ .../oauth2/src/main/webapp/index.jsp | 52 +++++++ .../src/main/webapp/stylesheets/main.css | 20 +++ appengine-java11/spanner/pom.xml | 5 +- 15 files changed, 586 insertions(+), 11 deletions(-) create mode 100644 appengine-java11/oauth2/README.md create mode 100644 appengine-java11/oauth2/pom.xml create mode 100644 appengine-java11/oauth2/src/main/appengine/app.yaml create mode 100644 appengine-java11/oauth2/src/main/java/com/example/appengine/LogoutServlet.java create mode 100644 appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java create mode 100644 appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java create mode 100644 appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java create mode 100644 appengine-java11/oauth2/src/main/webapp/WEB-INF/web.xml create mode 100644 appengine-java11/oauth2/src/main/webapp/index.jsp create mode 100644 appengine-java11/oauth2/src/main/webapp/stylesheets/main.css diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh index 4907bec58ae..89e660b41e7 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -67,7 +67,7 @@ fi # Package local jetty dependency for Java11 samples if [[ "$JAVA_VERSION" == "11" ]]; then cd appengine-java11/appengine-simple-jetty-main/ - mvn package + mvn install cd ../../ fi diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml index 8a717c5c189..521b1e0f9c0 100644 --- a/appengine-java11/gaeinfo/pom.xml +++ b/appengine-java11/gaeinfo/pom.xml @@ -42,11 +42,10 @@ Copyright 2019 Google Inc. - com.google.appengine.demo + com.example.appengine.demo simple-jetty-main 1 - system - ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + provided diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml index d298d413be3..34a26badbaf 100644 --- a/appengine-java11/guestbook-cloud-firestore/pom.xml +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -31,11 +31,10 @@ - com.google.appengine.demo + com.example.appengine.demo simple-jetty-main 1 - system - ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + provided diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml index 6b273ebb12b..8b685e22e3d 100644 --- a/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml +++ b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml @@ -13,4 +13,4 @@ runtime: java11 instance_class: F2 -entrypoint: 'java -cp * com.google.appengine.demo.jettymain.Main guestbook.war' +entrypoint: 'java -cp * com.example.appengine.demo.jettymain.Main guestbook.war' diff --git a/appengine-java11/oauth2/README.md b/appengine-java11/oauth2/README.md new file mode 100644 index 00000000000..02e42d1c933 --- /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 http://.appspot.com URL. diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml new file mode 100644 index 00000000000..6b211b8eeed --- /dev/null +++ b/appengine-java11/oauth2/pom.xml @@ -0,0 +1,133 @@ + + + + + 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.28.0 + provided + + + + com.google.oauth-client + google-oauth-client-servlet + 1.28.0 + provided + + + + com.google.apis + google-api-services-oauth2 + v2-rev131-1.23.0 + provided + + + + javax.servlet + javax.servlet-api + 4.0.1 + jar + provided + + + + jstl + jstl + 1.2 + provided + + + + + + oauth2 + + + com.google.cloud.tools + appengine-maven-plugin + 2.0.0-rc5 + + oauth2 + + + + + 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/oauth2/src/main/appengine/app.yaml b/appengine-java11/oauth2/src/main/appengine/app.yaml new file mode 100644 index 00000000000..67dfdabed19 --- /dev/null +++ b/appengine-java11/oauth2/src/main/appengine/app.yaml @@ -0,0 +1,21 @@ +# 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' + +env_variables: + CLIENT_ID: '' + CLIENT_SECRET: '' 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..8fc5c0d5925 --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java @@ -0,0 +1,51 @@ +/* + * 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.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); + } +} 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..8f2b2fb6711 --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.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 com.example.appengine; + +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); + } +} 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..30a33326ea6 --- /dev/null +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.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 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(); + } + + /** + * 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(); + } + + /** + * 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(); + } + + /** 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; + } +} 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..333848c917d --- /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..bdced8c509b --- /dev/null +++ b/appengine-java11/oauth2/src/main/webapp/stylesheets/main.css @@ -0,0 +1,20 @@ +/* + 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. +*/ + +body { + font-family: Roboto, Helvetica, sans-serif; + color: #4285F4; +} diff --git a/appengine-java11/spanner/pom.xml b/appengine-java11/spanner/pom.xml index 69d7a68f4c4..bcf3e002804 100644 --- a/appengine-java11/spanner/pom.xml +++ b/appengine-java11/spanner/pom.xml @@ -45,11 +45,10 @@ - com.google.appengine.demo + com.example.appengine.demo simple-jetty-main 1 - system - ${project.basedir}/../appengine-simple-jetty-main/target/simple-jetty-main-1.jar + provided From 1f0a55ec08d79ff6e3eca82e3c6d26cc96fcf33e Mon Sep 17 00:00:00 2001 From: BenWhitehead Date: Thu, 2 May 2019 16:18:30 -0400 Subject: [PATCH 10/49] Add snippet for Collection Group Query (#1399) * Bump `com.google.cloud:google-cloud-firestore` to `1.2.0` which includes the new functionality * Add `hashCode` for `City.java` --- firestore/pom.xml | 2 +- .../firestore/snippets/QueryDataSnippets.java | 68 +++++++++++++++++-- .../firestore/snippets/model/City.java | 5 ++ 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/firestore/pom.xml b/firestore/pom.xml index e4282911c75..39b7a3bc1be 100644 --- a/firestore/pom.xml +++ b/firestore/pom.xml @@ -45,7 +45,7 @@ com.google.cloud google-cloud-firestore - 0.81.0-beta + 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); + } } From 62006b7ba2722db66e67f5da473ee9fa2bbc34cd Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 3 May 2019 10:51:40 -0700 Subject: [PATCH 11/49] Java 11 ReadMe updates (#1401) * Update readmes * Fix XML and ReadMe instructions --- appengine-java11/README.md | 2 +- appengine-java11/gaeinfo/README.md | 30 +++++++++---------- .../guestbook-cloud-firestore/README.md | 22 +++++++++++++- .../src/main/webapp/WEB-INF/web.xml | 2 +- appengine-java11/spanner/README.md | 2 +- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/appengine-java11/README.md b/appengine-java11/README.md index 80588b0c969..3505746bec9 100644 --- a/appengine-java11/README.md +++ b/appengine-java11/README.md @@ -1,6 +1,6 @@ # 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] diff --git a/appengine-java11/gaeinfo/README.md b/appengine-java11/gaeinfo/README.md index e0b57079d31..4117413536b 100644 --- a/appengine-java11/gaeinfo/README.md +++ b/appengine-java11/gaeinfo/README.md @@ -1,11 +1,25 @@ # 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: @@ -26,20 +40,6 @@ Main class to your classpath: mvn package ``` -## Setup you Google Cloud 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` - ## Deploy - Deploy to App Engine standard environment using the following Maven command. diff --git a/appengine-java11/guestbook-cloud-firestore/README.md b/appengine-java11/guestbook-cloud-firestore/README.md index 707cd0b771c..8f1e068ebb5 100644 --- a/appengine-java11/guestbook-cloud-firestore/README.md +++ b/appengine-java11/guestbook-cloud-firestore/README.md @@ -11,7 +11,7 @@ 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 +## Setup your Google Cloud Platform Project * Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/) @@ -22,6 +22,26 @@ libraries. 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. 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 index a78995dacad..211f89c251d 100644 --- 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 @@ -1,3 +1,4 @@ + - Date: Mon, 6 May 2019 13:44:02 -0700 Subject: [PATCH 13/49] Container analysis update (#1402) * refactored container analysis * added new samples --- .../example/containeranalysis/CreateNote.java | 60 +++ .../containeranalysis/CreateOccurrence.java | 60 +++ .../example/containeranalysis/DeleteNote.java | 39 ++ .../containeranalysis/DeleteOccurrence.java | 39 ++ .../containeranalysis/GetDiscoveryInfo.java | 44 +++ .../example/containeranalysis/GetNote.java | 42 +++ .../containeranalysis/GetOccurrence.java | 42 +++ .../HighVulnerabilitiesForImage.java | 50 +++ .../OccurrencesForImage.java | 48 +++ .../containeranalysis/OccurrencesForNote.java | 54 +++ .../PollDiscoveryOccurrenceFinished.java | 78 ++++ .../com/example/containeranalysis/PubSub.java | 91 +++++ .../example/containeranalysis/Samples.java | 346 ------------------ .../VulnerabilityOccurrencesForImage.java | 46 +++ .../containeranalysis/SamplesTest.java | 237 ++++++++---- 15 files changed, 865 insertions(+), 411 deletions(-) create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateNote.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/CreateOccurrence.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteNote.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/DeleteOccurrence.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetDiscoveryInfo.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetNote.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/GetOccurrence.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/HighVulnerabilitiesForImage.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForImage.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/OccurrencesForNote.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/PollDiscoveryOccurrenceFinished.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.java delete mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/Samples.java create mode 100644 container-registry/container-analysis/src/main/java/com/example/containeranalysis/VulnerabilityOccurrencesForImage.java 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..069f18d2c73 --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PollDiscoveryOccurrenceFinished.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 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; + String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + resourceUrl + "\""; + while (discoveryOccurrence == null) { + for (Occurrence o : client.listOccurrences(projectName, filterStr).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/PubSub.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.java new file mode 100644 index 00000000000..abf1051472c --- /dev/null +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.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 PubSub { + // 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/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/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..b364e23bbb1 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); + PubSub.createOccurrenceSubscription(subId, PROJECT_ID); } catch (StatusRuntimeException e) { System.out.println("subscription " + subId + " already exists"); } Subscriber subscriber = null; - Samples.MessageReceiverExample receiver = new Samples.MessageReceiverExample(); + PubSub.MessageReceiverExample receiver = new PubSub.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); + } } From ee82760317eb4e49459371280743703f9f150678 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Mon, 6 May 2019 20:21:54 -0700 Subject: [PATCH 14/49] Add new Sample Format guidelines. (#1406) * Add SAMPLE_FORMAT.md. * Add best practices. * Update Contributing.md. * Better exception example. --- CONTRIBUTING.md | 8 +-- SAMPLE_FORMAT.md | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 SAMPLE_FORMAT.md 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/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 From 51730290c6cf97c4c23938186d2e1dff096e9f26 Mon Sep 17 00:00:00 2001 From: ajaaym <34161822+ajaaym@users.noreply.github.com> Date: Tue, 7 May 2019 17:47:14 -0400 Subject: [PATCH 15/49] Example for pubsub authenticated push (#1407) --- appengine-java8/pubsub/README.md | 24 ++++ appengine-java8/pubsub/pom.xml | 5 + .../appengine/pubsub/MessageRepository.java | 24 +++- .../pubsub/MessageRepositoryImpl.java | 74 +++++++++++- .../pubsub/PubSubAuthenticatedPush.java | 112 ++++++++++++++++++ .../example/appengine/pubsub/PubSubHome.java | 99 ++++++++++++++-- .../appengine/pubsub/PubSubPublish.java | 11 +- .../example/appengine/pubsub/PubSubPush.java | 2 + .../pubsub/src/main/webapp/index.jsp | 24 +--- 9 files changed, 327 insertions(+), 48 deletions(-) create mode 100644 appengine-java8/pubsub/src/main/java/com/example/appengine/pubsub/PubSubAuthenticatedPush.java diff --git a/appengine-java8/pubsub/README.md b/appengine-java8/pubsub/README.md index c3294dcfb5e..2cb9314f3f3 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#L36). + +``` +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 fc40186461e..d3e9750c666 100644 --- a/appengine-java8/pubsub/pom.xml +++ b/appengine-java8/pubsub/pom.xml @@ -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() %> From 427bf719081764f307c4b7a23d460312918b2976 Mon Sep 17 00:00:00 2001 From: ajaaym <34161822+ajaaym@users.noreply.github.com> Date: Tue, 7 May 2019 17:58:34 -0400 Subject: [PATCH 16/49] Pub/Sub fix markup (#1408) --- appengine-java8/pubsub/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appengine-java8/pubsub/README.md b/appengine-java8/pubsub/README.md index 2cb9314f3f3..b6c0aa16916 100644 --- a/appengine-java8/pubsub/README.md +++ b/appengine-java8/pubsub/README.md @@ -56,7 +56,7 @@ gcloud beta pubsub subscriptions create \ - 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#L36). +`--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 \ From d3d5ec44f158814d6cdd7a7963444f7b0d3d6e33 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 7 May 2019 15:25:13 -0700 Subject: [PATCH 17/49] [WIP] Java 11 Region Tags (#1405) * Guestbook region tags * simple jetty main region tags * rename hello world * fix license * renamed * Fix license * Task region tags * fix errors * Add parent to pom.xml * Add oauth region tags * Update firestore instance * Fix styling * fix exception --- .../example/appengine/demo/jettymain/Main.java | 2 ++ .../Main.java | 4 +++- .../README.md | 0 appengine-java11/custom-entrypoint/app.yaml | 18 ++++++++++++++++++ appengine-java11/gaeinfo/pom.xml | 2 +- .../main/webapp/WEB-INF/templates/index.html | 2 +- .../guestbook-cloud-firestore/pom.xml | 14 ++++++++++++-- .../src/main/appengine/app.yaml | 2 ++ .../java/com/example/guestbook/Greeting.java | 3 ++- .../java/com/example/guestbook/Guestbook.java | 9 ++++++--- .../com/example/guestbook/Persistence.java | 18 +++++++++++------- .../guestbook/SignGuestbookServlet.java | 6 ++++-- .../src/main/webapp/index.jsp | 7 ++++--- appengine-java11/hello-world/app.yaml | 2 -- .../http-server/src/main/appengine/app.yaml | 14 ++++++++++++++ .../main/java/com/example/appengine/Main.java | 4 ++-- appengine-java11/oauth2/pom.xml | 2 ++ .../oauth2/src/main/appengine/app.yaml | 2 ++ .../Oauth2AuthorizationCodeServlet.java | 2 ++ .../appengine/Oauth2CallbackServlet.java | 2 ++ .../main/java/com/example/appengine/Utils.java | 4 ++++ .../oauth2/src/main/webapp/index.jsp | 2 +- .../src/main/webapp/stylesheets/main.css | 2 +- .../tasks-handler/src/main/appengine/app.yaml | 7 +++++++ .../taskhandler/TaskHandlerController.java | 2 ++ appengine-java11/tasks/pom.xml | 2 ++ .../main/java/com/example/task/CreateTask.java | 2 ++ 27 files changed, 109 insertions(+), 27 deletions(-) rename appengine-java11/{hello-world => custom-entrypoint}/Main.java (92%) rename appengine-java11/{hello-world => custom-entrypoint}/README.md (100%) create mode 100644 appengine-java11/custom-entrypoint/app.yaml delete mode 100644 appengine-java11/hello-world/app.yaml 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 index 1b28f9c3520..8007fc05740 100644 --- 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 @@ -16,6 +16,7 @@ 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; @@ -61,3 +62,4 @@ public static void main(String[] args) throws Exception { server.join(); } } +// [END gae_java11_server] diff --git a/appengine-java11/hello-world/Main.java b/appengine-java11/custom-entrypoint/Main.java similarity index 92% rename from appengine-java11/hello-world/Main.java rename to appengine-java11/custom-entrypoint/Main.java index 1f07a6e3fdb..7f83c5c3c76 100644 --- a/appengine-java11/hello-world/Main.java +++ b/appengine-java11/custom-entrypoint/Main.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 Google Inc. + * 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. @@ -14,6 +14,7 @@ * limitations under the License. */ +// [START gae_java11_simple_server] import com.sun.net.httpserver.HttpServer; import java.io.IOException; import java.io.OutputStream; @@ -38,3 +39,4 @@ public static void main(String[] args) throws IOException { server.start(); } } +// [END gae_java11_simple_server] diff --git a/appengine-java11/hello-world/README.md b/appengine-java11/custom-entrypoint/README.md similarity index 100% rename from appengine-java11/hello-world/README.md rename to appengine-java11/custom-entrypoint/README.md 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/pom.xml b/appengine-java11/gaeinfo/pom.xml index 521b1e0f9c0..8b9727b0ab6 100644 --- a/appengine-java11/gaeinfo/pom.xml +++ b/appengine-java11/gaeinfo/pom.xml @@ -1,5 +1,5 @@ + + com.google.cloud.samples + shared-configuration + 1.0.11 + + 11 11 @@ -36,14 +46,14 @@ 1 provided
- + com.google.cloud google-cloud-firestore 0.81.0-beta provided - + com.google.guava guava diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml index 8b685e22e3d..319f597f761 100644 --- a/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml +++ b/appengine-java11/guestbook-cloud-firestore/src/main/appengine/app.yaml @@ -11,6 +11,8 @@ # 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 index 1df05955874..e1fb8b22e19 100644 --- 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 @@ -16,7 +16,6 @@ package com.example.guestbook; - import com.google.common.base.MoreObjects; import java.util.Date; import java.util.HashMap; @@ -51,6 +50,7 @@ public Greeting(String book, String content, String 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); @@ -59,6 +59,7 @@ public void save() { // Add Greeting to Guestbook with random id. book.getBookRef().collection("Greetings").add(greetingData); + // [END gae_java11_firestore_greeting] } @Override 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 index dc816fa43f3..ee33af8c39c 100644 --- 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 @@ -46,17 +46,19 @@ public Guestbook(String book) { // Construct the Guestbook data. Map bookData = new HashMap<>(); bookData.put("name", this.book); - + // [START gae_java11_firestore_book] // Get Guestbook reference in the collection. bookRef = getFirestore().collection("Guestbooks").document(this.book); // Add Guestbook to collection. bookRef.set(bookData); + // [END gae_java11_firestore_book] } public DocumentReference getBookRef() { return bookRef; } + // [START gae_java11_firestore_get_greetings] /** Get greetings for the Guestbook */ public List getGreetings() { // Initialize a List for Greetings. @@ -71,12 +73,13 @@ public List getGreetings() { for (QueryDocumentSnapshot greeting : querySnapshot.getDocuments()) { greetings.add(greeting.toObject(Greeting.class)); } - } catch (Exception InterruptedException) { - System.out.println("Nothing to query."); + } catch (Exception e) { + System.out.println(e.getMessage()); } return greetings.build(); } + // [END gae_java11_firestore_get_greetings] @Override public boolean equals(Object obj) { 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 index 48b974b4ed2..fefbf40503a 100644 --- 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 @@ -16,27 +16,31 @@ package com.example.guestbook; +// [START gae_java11_firestore_dependencies] import com.google.cloud.firestore.Firestore; import com.google.cloud.firestore.FirestoreOptions; -import java.util.concurrent.atomic.AtomicReference; +// [END gae_java11_firestore_dependencies] /** Create a persistence connection to your Firestore instance. */ public class Persistence { - private static AtomicReference firestore = new AtomicReference<>(); + private static Firestore firestore; @SuppressWarnings("JavadocMethod") public static Firestore getFirestore() { - if (firestore.get() == null) { + if (firestore == null) { // Authorized Firestore service - firestore.set( - FirestoreOptions.newBuilder().setProjectId("YOUR-PROJECT-ID").build().getService()); + // [START gae_java11_firestore] + Firestore db = + FirestoreOptions.newBuilder().setProjectId("YOUR-PROJECT-ID").build().getService(); + // [END gae_java11_firestore] + firestore = db; } - return firestore.get(); + return firestore; } public static void setFirestore(Firestore firestore) { - Persistence.firestore.set(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 index e1c843f2ac5..7092bc2c139 100644 --- 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 @@ -16,16 +16,17 @@ package com.example.guestbook; +// [START gae_java11_form_data] import java.io.IOException; -import javax.servlet.annotation.WebServlet; 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") +@WebServlet(name = "SignGuestbookServlet", value = "/sign") public class SignGuestbookServlet extends HttpServlet { // Process the HTTP POST of the form @@ -44,3 +45,4 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) resp.sendRedirect("/index.jsp?guestbookName=" + guestbookName); } } +// [END gae_java11_form_data] diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp index d87f284b537..1e7224573e4 100644 --- a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp +++ b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp @@ -51,9 +51,9 @@ limitations under the License.
-

Write Your Greeting

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

Write Your Greeting

+ <%-- [START gae_java11_form] --%>
@@ -72,8 +72,9 @@ limitations under the License.
+ <%-- [END gae_java11_form] --%> - + <%-- List greetings --%>

Greetings:

<% if (greetings.isEmpty()) { %> diff --git a/appengine-java11/hello-world/app.yaml b/appengine-java11/hello-world/app.yaml deleted file mode 100644 index f142d2b4f06..00000000000 --- a/appengine-java11/hello-world/app.yaml +++ /dev/null @@ -1,2 +0,0 @@ -runtime: java11 -entrypoint: java Main.java diff --git a/appengine-java11/http-server/src/main/appengine/app.yaml b/appengine-java11/http-server/src/main/appengine/app.yaml index abfdc495a95..8848aeed6c3 100644 --- a/appengine-java11/http-server/src/main/appengine/app.yaml +++ b/appengine-java11/http-server/src/main/appengine/app.yaml @@ -1,2 +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 # No need for an entrypoint with single fatjar with correct manifest class-path entry. 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 index 4f71ecce0d8..b0bbfb76f7e 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2019 Google Inc. + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + package com.example.appengine; import com.sun.net.httpserver.HttpServer; diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml index 6b211b8eeed..7b3b0dd6868 100644 --- a/appengine-java11/oauth2/pom.xml +++ b/appengine-java11/oauth2/pom.xml @@ -52,6 +52,7 @@ + com.google.oauth-client google-oauth-client @@ -72,6 +73,7 @@ v2-rev131-1.23.0 provided + javax.servlet diff --git a/appengine-java11/oauth2/src/main/appengine/app.yaml b/appengine-java11/oauth2/src/main/appengine/app.yaml index 67dfdabed19..72d7e6ffe74 100644 --- a/appengine-java11/oauth2/src/main/appengine/app.yaml +++ b/appengine-java11/oauth2/src/main/appengine/app.yaml @@ -16,6 +16,8 @@ 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/Oauth2AuthorizationCodeServlet.java b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java index 8fc5c0d5925..2312f4cf438 100644 --- a/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2AuthorizationCodeServlet.java @@ -16,6 +16,7 @@ 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; @@ -49,3 +50,4 @@ protected String getUserId(HttpServletRequest req) throws ServletException, IOEx 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 index 8f2b2fb6711..bb17aad853c 100644 --- a/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Oauth2CallbackServlet.java @@ -16,6 +16,7 @@ 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; @@ -75,3 +76,4 @@ protected String getUserId(HttpServletRequest req) throws ServletException, IOEx 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 index 30a33326ea6..f261d1e583b 100644 --- a/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java +++ b/appengine-java11/oauth2/src/main/java/com/example/appengine/Utils.java @@ -68,6 +68,7 @@ static String getRedirectUri(HttpServletRequest req) { 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. @@ -79,6 +80,7 @@ public static GoogleAuthorizationCodeFlow newFlow() throws IOException { .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 @@ -89,6 +91,7 @@ static String getUserId(HttpServletRequest req) throws ServletException, IOExcep 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 = @@ -101,4 +104,5 @@ public static String getUserInfo(Credential credential) throws IOException { String username = userInfo.getGivenName(); return username; } + // [END gae_java11_oauth2_get_user] } diff --git a/appengine-java11/oauth2/src/main/webapp/index.jsp b/appengine-java11/oauth2/src/main/webapp/index.jsp index 333848c917d..c4340770761 100644 --- a/appengine-java11/oauth2/src/main/webapp/index.jsp +++ b/appengine-java11/oauth2/src/main/webapp/index.jsp @@ -1,7 +1,7 @@ + com.google.cloud google-cloud-tasks 0.87.0-beta provided + 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 index 4f9d29ac224..05fcda4eecc 100644 --- a/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java +++ b/appengine-java11/tasks/src/main/java/com/example/task/CreateTask.java @@ -16,6 +16,7 @@ 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; @@ -63,3 +64,4 @@ public static void main(String[] args) throws Exception { } } } +// [END gae_java11_create_task] From 7b355b5191bdaf6757ec80e4ccaf42de48831a60 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Wed, 8 May 2019 09:21:45 -0700 Subject: [PATCH 18/49] Update Java11 Spring Boot sample (#1409) * Update SpringBoot Sample * Update licenses * Fix test dependencies * Fix linting --- .../gaeinfo/src/main/appengine/app.yaml | 14 + .../spanner/src/main/appengine/app.yaml | 14 + .../.mvn/wrapper/maven-wrapper.properties | 1 - .../springboot-helloworld/README.md | 5 +- appengine-java11/springboot-helloworld/mvnw | 286 ------------------ .../springboot-helloworld/mvnw.cmd | 161 ---------- .../springboot-helloworld/pom.xml | 100 +++--- .../src/main/appengine/app.yaml | 22 +- .../springboot/SpringbootApplication.java | 18 ++ .../src/main/resources/application.properties | 13 + .../SpringbootApplicationTests.java | 17 -- 11 files changed, 135 insertions(+), 516 deletions(-) delete mode 100644 appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties delete mode 100755 appengine-java11/springboot-helloworld/mvnw delete mode 100644 appengine-java11/springboot-helloworld/mvnw.cmd delete mode 100644 appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java diff --git a/appengine-java11/gaeinfo/src/main/appengine/app.yaml b/appengine-java11/gaeinfo/src/main/appengine/app.yaml index e0faea3ceff..a98633567cc 100644 --- a/appengine-java11/gaeinfo/src/main/appengine/app.yaml +++ b/appengine-java11/gaeinfo/src/main/appengine/app.yaml @@ -1,3 +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/spanner/src/main/appengine/app.yaml b/appengine-java11/spanner/src/main/appengine/app.yaml index d40a811e1f8..ef5374484bb 100644 --- a/appengine-java11/spanner/src/main/appengine/app.yaml +++ b/appengine-java11/spanner/src/main/appengine/app.yaml @@ -1,3 +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 spanner.war' diff --git a/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties b/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 71793467167..00000000000 --- a/appengine-java11/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1 +0,0 @@ -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip diff --git a/appengine-java11/springboot-helloworld/README.md b/appengine-java11/springboot-helloworld/README.md index bceaec89747..720a1e4fb42 100644 --- a/appengine-java11/springboot-helloworld/README.md +++ b/appengine-java11/springboot-helloworld/README.md @@ -1,9 +1,6 @@ # Spring Boot Application Google App Engine Standard with Java 11 -This sample shows how to deploy a Spring Boot application with an exploded fatjar -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. +This sample shows how to deploy a Spring Boot application to Google App Engine. ## Setup diff --git a/appengine-java11/springboot-helloworld/mvnw b/appengine-java11/springboot-helloworld/mvnw deleted file mode 100755 index 5551fde8e7d..00000000000 --- a/appengine-java11/springboot-helloworld/mvnw +++ /dev/null @@ -1,286 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir -# -# Optional ENV vars -# ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files -# ---------------------------------------------------------------------------- - -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi - - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi - -fi - -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" - fi - fi - ;; -esac - -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` - fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" - - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi - done - - saveddir=`pwd` - - M2_HOME=`dirname "$PRG"`/.. - - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` - - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi - -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi - -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" - # TODO classpath? -fi - -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi - -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi -fi - -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi - -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." -fi - -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher - -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { - - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi - - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} - -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} - -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; -fi - -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" - fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi - fi -fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" - -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` -fi - -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/appengine-java11/springboot-helloworld/mvnw.cmd b/appengine-java11/springboot-helloworld/mvnw.cmd deleted file mode 100644 index e5cfb0ae9ea..00000000000 --- a/appengine-java11/springboot-helloworld/mvnw.cmd +++ /dev/null @@ -1,161 +0,0 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml index aa9012d9038..db2c3a9fb93 100644 --- a/appengine-java11/springboot-helloworld/pom.xml +++ b/appengine-java11/springboot-helloworld/pom.xml @@ -1,4 +1,16 @@ + 4.0.0 @@ -6,20 +18,42 @@ springboot-helloworld-j11 0.0.1-SNAPSHOT - + - org.springframework.boot - spring-boot-starter-parent - 2.1.1.RELEASE - + com.google.cloud.samples + shared-configuration + 1.0.11 - 11 - 11 - 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 @@ -34,49 +68,25 @@ - org.springframework.boot - spring-boot-starter-jetty - - - - org.springframework.boot - spring-boot-starter-test - test + org.springframework.boot + spring-boot-starter-jetty + 2.1.4.RELEASE - org.springframework.boot - spring-boot-maven-plugin - - - - org.springframework.boot.experimental - spring-boot-thin-layout - 1.0.13.RELEASE - - - - - - - org.springframework.boot.experimental - spring-boot-thin-maven-plugin - 1.0.13.RELEASE - - ${project.build.directory}/appengine-staging - - - - resolve - - resolve - - false - - + org.springframework.boot + spring-boot-maven-plugin + 2.1.4.RELEASE + + + + repackage + + + diff --git a/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml b/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml index b5120153d4a..f584d9c79f8 100644 --- a/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml +++ b/appengine-java11/springboot-helloworld/src/main/appengine/app.yaml @@ -1,4 +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 -# The entrypoint here is mandatory as the appengine-staging area contains an exploded fatjar -entrypoint: 'java -XX:MaxRAM=256m -XX:ActiveProcessorCount=2 -Xmx32m -Dthin.root=. -jar springboot-thin-j11-0.0.1-SNAPSHOT.jar' + +# 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 index 100ccac8b82..9a4726c8096 100644 --- 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 @@ -1,5 +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. + */ + 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; @@ -19,3 +36,4 @@ public String hello() { } } +// [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 index e69de29bb2d..88fcbaa4554 100644 --- a/appengine-java11/springboot-helloworld/src/main/resources/application.properties +++ 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/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java b/appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java deleted file mode 100644 index 0c29b826162..00000000000 --- a/appengine-java11/springboot-helloworld/src/test/java/com/example/appengine/springboot/SpringbootApplicationTests.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.appengine.springboot; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class SpringbootApplicationTests { - - @Test - public void contextLoads() { - } - -} - From 3656dad64db0be7353b99d45dab814fa1cce2553 Mon Sep 17 00:00:00 2001 From: BenWhitehead Date: Wed, 8 May 2019 16:40:01 -0400 Subject: [PATCH 19/49] docs(samples): Update datastore_basic_entity sample to include `taskKey` definition (#1350) --- .../test/java/com/google/datastore/snippets/ConceptsTest.java | 3 +++ 1 file changed, 3 insertions(+) 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) From 204b5fbc317ae473e120f703ee19b886d4603917 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 10 May 2019 12:52:06 -0700 Subject: [PATCH 20/49] Add Frameworks Samples (#1411) * micronaut helloworld sample * Update readmes * Add ktor sample * Add Quarkus sample * Add vertx sample * Add Framework samples * Add annotation * Update endpoint * Update Micronaut tests * Update appengine plugin version * Add license * Respond to PR comments * update spark imports * micronaut styling * More styling updates * Rollback plugin version --- appengine-java11/gaeinfo/pom.xml | 2 +- .../guestbook-cloud-firestore/pom.xml | 2 +- appengine-java11/http-server/pom.xml | 2 +- appengine-java11/kotlin-ktor/README.md | 20 ++ appengine-java11/kotlin-ktor/app.yaml | 17 ++ appengine-java11/kotlin-ktor/pom.xml | 179 +++++++++++++++ .../kotlin-ktor/resources/application.conf | 25 ++ .../kotlin-ktor/resources/logback.xml | 28 +++ .../kotlin-ktor/src/Application.kt | 45 ++++ .../kotlin-ktor/test/ApplicationTest.kt | 38 +++ .../micronaut-helloworld/README.md | 20 ++ .../micronaut-helloworld/micronaut-cli.yml | 19 ++ appengine-java11/micronaut-helloworld/pom.xml | 217 ++++++++++++++++++ .../src/main/appengine/app.yaml | 16 ++ .../com/example/appengine/Application.java | 26 +++ .../example/appengine/HelloController.java | 31 +++ .../src/main/resources/application.yml | 17 ++ .../src/main/resources/logback.xml | 28 +++ .../appengine/HelloControllerTest.java | 56 +++++ appengine-java11/oauth2/pom.xml | 2 +- appengine-java11/quarkus-helloworld/README.md | 20 ++ appengine-java11/quarkus-helloworld/pom.xml | 109 +++++++++ .../src/main/appengine/app.yaml | 19 ++ .../appengine/quarkus/HelloResource.java | 32 +++ .../META-INF/microprofile-config.properties | 13 ++ .../appengine/quarkus/HelloResourceTest.java | 32 +++ appengine-java11/spanner/pom.xml | 2 +- .../sparkjava-helloworld/README.md | 20 ++ appengine-java11/sparkjava-helloworld/pom.xml | 112 +++++++++ .../src/main/appengine/app.yaml | 16 ++ .../com/example/appengine/sparkdemo/Main.java | 28 +++ .../springboot-helloworld/README.md | 3 +- .../springboot-helloworld/pom.xml | 2 +- appengine-java11/tasks-handler/pom.xml | 2 +- appengine-java11/vertx-helloworld/README.md | 54 +++++ appengine-java11/vertx-helloworld/pom.xml | 108 +++++++++ .../src/main/appengine/app.yaml | 18 ++ .../appengine/vertxhello/Application.java | 64 ++++++ .../example/appengine/vertxhello/Main.java | 28 +++ .../appengine/vertxhello/ApplicationTest.java | 72 ++++++ 40 files changed, 1536 insertions(+), 8 deletions(-) create mode 100644 appengine-java11/kotlin-ktor/README.md create mode 100644 appengine-java11/kotlin-ktor/app.yaml create mode 100644 appengine-java11/kotlin-ktor/pom.xml create mode 100644 appengine-java11/kotlin-ktor/resources/application.conf create mode 100644 appengine-java11/kotlin-ktor/resources/logback.xml create mode 100644 appengine-java11/kotlin-ktor/src/Application.kt create mode 100644 appengine-java11/kotlin-ktor/test/ApplicationTest.kt create mode 100644 appengine-java11/micronaut-helloworld/README.md create mode 100644 appengine-java11/micronaut-helloworld/micronaut-cli.yml create mode 100644 appengine-java11/micronaut-helloworld/pom.xml create mode 100644 appengine-java11/micronaut-helloworld/src/main/appengine/app.yaml create mode 100644 appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/Application.java create mode 100644 appengine-java11/micronaut-helloworld/src/main/java/com/example/appengine/HelloController.java create mode 100644 appengine-java11/micronaut-helloworld/src/main/resources/application.yml create mode 100644 appengine-java11/micronaut-helloworld/src/main/resources/logback.xml create mode 100644 appengine-java11/micronaut-helloworld/src/test/java/com/example/appengine/HelloControllerTest.java create mode 100644 appengine-java11/quarkus-helloworld/README.md create mode 100644 appengine-java11/quarkus-helloworld/pom.xml create mode 100644 appengine-java11/quarkus-helloworld/src/main/appengine/app.yaml create mode 100644 appengine-java11/quarkus-helloworld/src/main/java/com/example/appengine/quarkus/HelloResource.java create mode 100644 appengine-java11/quarkus-helloworld/src/main/resources/META-INF/microprofile-config.properties create mode 100644 appengine-java11/quarkus-helloworld/src/test/java/com/example/appengine/quarkus/HelloResourceTest.java create mode 100644 appengine-java11/sparkjava-helloworld/README.md create mode 100644 appengine-java11/sparkjava-helloworld/pom.xml create mode 100644 appengine-java11/sparkjava-helloworld/src/main/appengine/app.yaml create mode 100644 appengine-java11/sparkjava-helloworld/src/main/java/com/example/appengine/sparkdemo/Main.java create mode 100644 appengine-java11/vertx-helloworld/README.md create mode 100644 appengine-java11/vertx-helloworld/pom.xml create mode 100644 appengine-java11/vertx-helloworld/src/main/appengine/app.yaml create mode 100644 appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Application.java create mode 100644 appengine-java11/vertx-helloworld/src/main/java/com/example/appengine/vertxhello/Main.java create mode 100644 appengine-java11/vertx-helloworld/src/test/java/com/example/appengine/vertxhello/ApplicationTest.java diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml index 8b9727b0ab6..fd106c685a8 100644 --- a/appengine-java11/gaeinfo/pom.xml +++ b/appengine-java11/gaeinfo/pom.xml @@ -124,7 +124,7 @@ Copyright 2019 Google LLC com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 gaeinfo diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml index 85bb4111418..025b22dcaca 100644 --- a/appengine-java11/guestbook-cloud-firestore/pom.xml +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -80,7 +80,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 guestbook diff --git a/appengine-java11/http-server/pom.xml b/appengine-java11/http-server/pom.xml index 6cf4e97417d..8a8f34d2bb5 100644 --- a/appengine-java11/http-server/pom.xml +++ b/appengine-java11/http-server/pom.xml @@ -37,7 +37,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 http-server diff --git a/appengine-java11/kotlin-ktor/README.md b/appengine-java11/kotlin-ktor/README.md new file mode 100644 index 00000000000..06a18770a94 --- /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 http://.appspot.com URL. 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..a772fd62b41 --- /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-rc6 + + 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..f85b50717e4 --- /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 http://.appspot.com URL. 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..8c09925169a --- /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-rc6 + + 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/pom.xml b/appengine-java11/oauth2/pom.xml index 7b3b0dd6868..bb0f3631e8f 100644 --- a/appengine-java11/oauth2/pom.xml +++ b/appengine-java11/oauth2/pom.xml @@ -98,7 +98,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 oauth2 diff --git a/appengine-java11/quarkus-helloworld/README.md b/appengine-java11/quarkus-helloworld/README.md new file mode 100644 index 00000000000..7f7908b0061 --- /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 http://.appspot.com URL. diff --git a/appengine-java11/quarkus-helloworld/pom.xml b/appengine-java11/quarkus-helloworld/pom.xml new file mode 100644 index 00000000000..6c6d3a941d1 --- /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-rc6 + + 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/pom.xml b/appengine-java11/spanner/pom.xml index bcf3e002804..6eb08637832 100644 --- a/appengine-java11/spanner/pom.xml +++ b/appengine-java11/spanner/pom.xml @@ -96,7 +96,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 spanner diff --git a/appengine-java11/sparkjava-helloworld/README.md b/appengine-java11/sparkjava-helloworld/README.md new file mode 100644 index 00000000000..fc25f885faf --- /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 http://.appspot.com URL. diff --git a/appengine-java11/sparkjava-helloworld/pom.xml b/appengine-java11/sparkjava-helloworld/pom.xml new file mode 100644 index 00000000000..8e5fd5e58ab --- /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-rc6 + + ${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 index 720a1e4fb42..84d1515e5a1 100644 --- a/appengine-java11/springboot-helloworld/README.md +++ b/appengine-java11/springboot-helloworld/README.md @@ -1,6 +1,7 @@ # Spring Boot Application Google App Engine Standard with Java 11 -This sample shows how to deploy a Spring Boot application to Google App Engine. +This sample shows how to deploy a [Spring Boot](https://spring.io/projects/spring-boot) +application to Google App Engine stadndard. ## Setup diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml index db2c3a9fb93..ef6d11efc08 100644 --- a/appengine-java11/springboot-helloworld/pom.xml +++ b/appengine-java11/springboot-helloworld/pom.xml @@ -92,7 +92,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 springboot-helloworld diff --git a/appengine-java11/tasks-handler/pom.xml b/appengine-java11/tasks-handler/pom.xml index bf27d85aa3d..23b4920c450 100644 --- a/appengine-java11/tasks-handler/pom.xml +++ b/appengine-java11/tasks-handler/pom.xml @@ -96,7 +96,7 @@ limitations under the License. com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc5 + 2.0.0-rc6 task-handler diff --git a/appengine-java11/vertx-helloworld/README.md b/appengine-java11/vertx-helloworld/README.md new file mode 100644 index 00000000000..d1945fac520 --- /dev/null +++ b/appengine-java11/vertx-helloworld/README.md @@ -0,0 +1,54 @@ +# Vertx 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 http://yourprojectid.appspot.com URL. + +## 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..95d413aa879 --- /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-rc6 + + ${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()); + })); + } +} From 57717fdaf79357028830317fce31ab1d30457ebb Mon Sep 17 00:00:00 2001 From: Noah Negrey Date: Mon, 13 May 2019 08:27:17 -0700 Subject: [PATCH 21/49] Update streaming sample to use non-deprecated method (#1413) --- dialogflow/cloud-client/pom.xml | 1392 +---------------- .../dialogflow/DetectIntentStream.java | 138 +- .../dialogflow/DetectIntentStreamIT.java | 37 +- .../dialogflow/KnowledgeBaseManagementIT.java | 11 +- 4 files changed, 64 insertions(+), 1514 deletions(-) diff --git a/dialogflow/cloud-client/pom.xml b/dialogflow/cloud-client/pom.xml index 4b955a1f5b4..82d9dd49b3f 100644 --- a/dialogflow/cloud-client/pom.xml +++ b/dialogflow/cloud-client/pom.xml @@ -40,7 +40,7 @@ com.google.cloud google-cloud-dialogflow - 0.70.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/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/KnowledgeBaseManagementIT.java b/dialogflow/cloud-client/src/test/java/com/example/dialogflow/KnowledgeBaseManagementIT.java index d6bdab305e2..877737779c3 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,11 @@ 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()) + && answer.getAnswer().contains("Cloud Storage")) { + answersFound++; + } } } // To make the test less flaky, check that half of the texts got a result. From e0d83adb4ff0acd3ad72545416c448002efbd0d5 Mon Sep 17 00:00:00 2001 From: MaxRossGoogle Date: Tue, 14 May 2019 09:56:53 -0700 Subject: [PATCH 22/49] Update example to not reference GAE (#1412) --- tasks/src/main/java/com/example/task/CreateHttpTask.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/src/main/java/com/example/task/CreateHttpTask.java b/tasks/src/main/java/com/example/task/CreateHttpTask.java index 9b4a1ac23d6..a1eed42320a 100644 --- a/tasks/src/main/java/com/example/task/CreateHttpTask.java +++ b/tasks/src/main/java/com/example/task/CreateHttpTask.java @@ -37,9 +37,9 @@ public static void main(String[] args) throws Exception { try (CloudTasksClient client = CloudTasksClient.create()) { // Variables provided by the system variables. // projectId = "my-project-id"; - // queueName = "my-appengine-queue"; + // queueName = "my-queue"; // location = "us-central1"; - // url = "https://.appspot.com/tasks/create"; + // url = "https://example.com/hellohandler"; String payload = "hello"; // Construct the fully qualified queue name. From e2c0229286c56d3b184861fa5883a41e99bb9410 Mon Sep 17 00:00:00 2001 From: Daniel Sanche Date: Tue, 14 May 2019 10:40:07 -0700 Subject: [PATCH 23/49] Container analysis filter (#1415) - updated filter statement - renamed pubsub file --- .../PollDiscoveryOccurrenceFinished.java | 12 ++++++++++-- .../{PubSub.java => Subscriptions.java} | 2 +- .../com/example/containeranalysis/SamplesTest.java | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) rename container-registry/container-analysis/src/main/java/com/example/containeranalysis/{PubSub.java => Subscriptions.java} (99%) 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 index 069f18d2c73..040fec7de00 100644 --- 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 @@ -43,9 +43,17 @@ public static Occurrence pollDiscoveryOccurrenceFinished(String resourceUrl, Str // find the discovery occurrence using a filter string Occurrence discoveryOccurrence = null; - String filterStr = "kind=\"DISCOVERY\" AND resourceUrl=\"" + resourceUrl + "\""; + // 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, filterStr).iterateAll()) { + 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; diff --git a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.java b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java similarity index 99% rename from container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.java rename to container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java index abf1051472c..bd80e4b94ec 100644 --- a/container-registry/container-analysis/src/main/java/com/example/containeranalysis/PubSub.java +++ b/container-registry/container-analysis/src/main/java/com/example/containeranalysis/Subscriptions.java @@ -31,7 +31,7 @@ import java.lang.InterruptedException; import java.util.concurrent.TimeUnit; -public class PubSub { +public class Subscriptions { // Handle incoming Occurrences using a Cloud Pub/Sub subscription public static int pubSub(String subId, long timeoutSeconds, String projectId) throws InterruptedException { 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 b364e23bbb1..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 @@ -200,12 +200,12 @@ public void testPubSub() throws Exception { int tries; ProjectSubscriptionName subName = ProjectSubscriptionName.of(PROJECT_ID, subId); try { - PubSub.createOccurrenceSubscription(subId, PROJECT_ID); + Subscriptions.createOccurrenceSubscription(subId, PROJECT_ID); } catch (StatusRuntimeException e) { System.out.println("subscription " + subId + " already exists"); } Subscriber subscriber = null; - PubSub.MessageReceiverExample receiver = new PubSub.MessageReceiverExample(); + Subscriptions.MessageReceiverExample receiver = new Subscriptions.MessageReceiverExample(); subscriber = Subscriber.newBuilder(subName, receiver).build(); subscriber.startAsync().awaitRunning(); From 0730123a2edbf09119ba482af6fa86d866b4f275 Mon Sep 17 00:00:00 2001 From: Ricardo Mendes <50331050+ricardosm-cit@users.noreply.github.com> Date: Tue, 14 May 2019 16:40:00 -0300 Subject: [PATCH 24/49] Add samples for Data Catalog lookupEntry (#1416) --- README.md | 1 + datacatalog/cloud-client/README.md | 31 +++++++ datacatalog/cloud-client/build.gradle | 41 ++++++++++ datacatalog/cloud-client/pom.xml | 59 ++++++++++++++ .../LookupEntryBigQueryDataset.java | 56 +++++++++++++ .../datacatalog/LookupEntryBigQueryTable.java | 61 ++++++++++++++ .../datacatalog/LookupEntryPubSubTopic.java | 56 +++++++++++++ .../example/datacatalog/LookupEntryTests.java | 81 +++++++++++++++++++ 8 files changed, 386 insertions(+) create mode 100644 datacatalog/cloud-client/README.md create mode 100644 datacatalog/cloud-client/build.gradle create mode 100644 datacatalog/cloud-client/pom.xml create mode 100644 datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java create mode 100644 datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryTable.java create mode 100644 datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryPubSubTopic.java create mode 100644 datacatalog/cloud-client/src/test/java/com/example/datacatalog/LookupEntryTests.java 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/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..b81737645fc --- /dev/null +++ b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.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 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()); + } + } +} 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/.+?$"); + } +} From 9e9120a1dd3fcaaf7875cef6ffe4db74bea4bc15 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Tue, 14 May 2019 15:14:02 -0700 Subject: [PATCH 25/49] Update comments in Task samples (#1418) --- tasks/README.md | 50 ++++++++----------- .../java/com/example/task/CreateHttpTask.java | 2 +- .../example/task/CreateHttpTaskWithToken.java | 2 +- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/tasks/README.md b/tasks/README.md index dd13bd1d576..f3e8fa8cea1 100644 --- a/tasks/README.md +++ b/tasks/README.md @@ -1,17 +1,12 @@ -# Google Cloud Tasks App Engine Queue Samples +# Google Cloud Tasks 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. +This sample demonstrates using the Cloud Tasks client library. `CreateHTTPTask.java` constructs a task with an HTTP target and pushes it to your queue. -`CreateHTTPTask.java` constructs a task with an HTTP target and OIDC token and pushes it -to your queue. +`CreateHTTPTask.java` constructs a task with an HTTP target and OIDC token and +pushes it to your queue. ## Initial Setup @@ -27,18 +22,7 @@ to your queue. To create a queue using the Cloud SDK, use the following gcloud command: ``` -gcloud beta tasks queues create-app-engine-queue my-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) - -``` -mvn appengine:deploy +gcloud beta tasks queues create ``` ## Run the Sample Using the Command Line @@ -61,7 +45,7 @@ export QUEUE_ID=my-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 +"projects/my-project/locations/us-central1/queues/my-queue", then the location is "us-central1"). ``` @@ -71,24 +55,32 @@ export LOCATION_ID= ### Using HTTP Push Queues Set an environment variable for the endpoint to your task handler. This is an -example url to send requests to the App Engine task handler: +example url: ``` -export URL=https://${PROJECT_ID}.appspot.com/tasks/create +export URL=https://example.com/taskshandler ``` -Running the sample will create a task and send the task to the specific URL -endpoint, with a payload specified: +Running the sample will create a task and add it to your queue. As the queue +processes each task, it will send the task to the specific URL endpoint: ``` mvn exec:java@HttpTask" ``` -### Using HTTP Targets with Authentication Headers +### Using HTTP Targets with Authentication Tokens + +Your Cloud Tasks [service account][sa], +(service-@gcp-sa-cloudtasks.iam.gserviceaccount.com), must +have the role of: `Service Account Token Creator` to generate a tokens. -In `CreateHttpTaskWithToken.java`, add your service account email in place of -`` to authenticate the OIDC token. +Create or use an existing [service account][sa] to replace `` +in `CreateHttpTaskWithToken.java`. This service account will be used to +authenticate the OIDC token. Running the sample with command: ``` mvn exec:java@WithToken" ``` + + +[sa]: https://cloud.google.com/iam/docs/service-accounts diff --git a/tasks/src/main/java/com/example/task/CreateHttpTask.java b/tasks/src/main/java/com/example/task/CreateHttpTask.java index a1eed42320a..6e8412426bb 100644 --- a/tasks/src/main/java/com/example/task/CreateHttpTask.java +++ b/tasks/src/main/java/com/example/task/CreateHttpTask.java @@ -39,7 +39,7 @@ public static void main(String[] args) throws Exception { // projectId = "my-project-id"; // queueName = "my-queue"; // location = "us-central1"; - // url = "https://example.com/hellohandler"; + // url = "https://example.com/taskhandler"; String payload = "hello"; // Construct the fully qualified queue name. diff --git a/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java index 0891d899c85..978ddcc91b1 100644 --- a/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java +++ b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java @@ -40,7 +40,7 @@ public static void main(String[] args) throws Exception { // projectId = "my-project-id"; // queueName = "my-appengine-queue"; // location = "us-central1"; - // url = "https://example.com/tasks/create"; + // url = "https://example.com/taskhandler"; String payload = "hello"; // Construct the fully qualified queue name. From 34003421a7c649dc711dd44f92f0a941aef47a21 Mon Sep 17 00:00:00 2001 From: Jonathan Simon Date: Tue, 14 May 2019 17:14:40 -0700 Subject: [PATCH 26/49] Add queryWithParameter to Cloud Spanner sample. (#1417) --- .../com/example/spanner/SpannerSample.java | 27 +++++++++++++++++++ .../com/example/spanner/SpannerSampleIT.java | 4 ++- 2 files changed, 30 insertions(+), 1 deletion(-) 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..86f7b02adfa 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 @@ -1013,6 +1013,29 @@ 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 @@ -1229,6 +1252,9 @@ static void run( case "writeusingdml": writeUsingDml(dbClient); break; + case "querywithparameter": + queryWithParameter(dbClient); + break; case "writewithtransactionusingdml": writeWithTransactionUsingDml(dbClient); break; @@ -1286,6 +1312,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..6c30a13d6c8 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 @@ -144,7 +144,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,6 +181,8 @@ 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"); From dbcc11ddd608b55726a2c9b2de9983e18cc5470b Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Wed, 15 May 2019 08:50:00 -0700 Subject: [PATCH 27/49] Task ReadMe changes (#1420) * Readme update * fix queue name --- tasks/README.md | 8 ++++---- .../java/com/example/task/CreateHttpTaskWithToken.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/README.md b/tasks/README.md index f3e8fa8cea1..e69b7360aa1 100644 --- a/tasks/README.md +++ b/tasks/README.md @@ -2,10 +2,10 @@ This sample demonstrates using the Cloud Tasks client library. -`CreateHTTPTask.java` constructs a task with an HTTP target and pushes it +`CreateHttpTask.java` constructs a task with an HTTP target and pushes it to your queue. -`CreateHTTPTask.java` constructs a task with an HTTP target and OIDC token and +`CreateHttpTask.java` constructs a task with an HTTP target and OIDC token and pushes it to your queue. ## Initial Setup @@ -39,7 +39,7 @@ 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-queue +export QUEUE_ID= ``` And finally the location ID, which can be discovered with @@ -52,7 +52,7 @@ location is "us-central1"). export LOCATION_ID= ``` -### Using HTTP Push Queues +### Creating Tasks with HTTP Targets Set an environment variable for the endpoint to your task handler. This is an example url: diff --git a/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java index 978ddcc91b1..f67cee97d32 100644 --- a/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java +++ b/tasks/src/main/java/com/example/task/CreateHttpTaskWithToken.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { try (CloudTasksClient client = CloudTasksClient.create()) { // Variables provided by the system variables. // projectId = "my-project-id"; - // queueName = "my-appengine-queue"; + // queueName = "my-queue"; // location = "us-central1"; // url = "https://example.com/taskhandler"; String payload = "hello"; From d50c7d4636fabb0fb13166a4d8caf8556df4f5aa Mon Sep 17 00:00:00 2001 From: Noah Negrey Date: Wed, 15 May 2019 15:16:22 -0700 Subject: [PATCH 28/49] TTS / Sentiment GA (#1421) --- .../DetectIntentWithSentimentAnalysis.java | 20 +++++++++---------- .../DetectIntentWithTextToSpeechResponse.java | 20 +++++++++---------- ...tIntentWithSentimentAndTextToSpeechIT.java | 2 +- .../dialogflow/KnowledgeBaseManagementIT.java | 3 +-- 4 files changed, 22 insertions(+), 23 deletions(-) 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/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 877737779c3..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 @@ -169,8 +169,7 @@ public void testDetectIntentKnowledge() throws Exception { KnowledgeAnswers knowledgeAnswers = allAnswers.get(text); if (knowledgeAnswers.getAnswersCount() > 0) { Answer answer = knowledgeAnswers.getAnswers(0); - if (text.equals(answer.getFaqQuestion()) && document.getName().equals(answer.getSource()) - && answer.getAnswer().contains("Cloud Storage")) { + if (text.equals(answer.getFaqQuestion()) && document.getName().equals(answer.getSource())) { answersFound++; } } From 8782eda09b5d468f878bc4403c6fe9599b88e658 Mon Sep 17 00:00:00 2001 From: Kristin Grace Galvin Date: Thu, 16 May 2019 11:56:35 -0700 Subject: [PATCH 29/49] Updated Infinite streaming sample (#1422) * adding result end time and color-coded result output * updated infinited streaming sample to use result_end_time * lint fixes * more comments and formatting updates * Fix speech test. * More test adjustments. --- .../speech/InfiniteStreamRecognize.java | 151 +++++++++++++++--- .../java/com/example/speech/Recognize.java | 1 - .../java/com/example/speech/RecognizeIT.java | 12 +- 3 files changed, 137 insertions(+), 27 deletions(-) diff --git a/speech/cloud-client/src/main/java/com/example/speech/InfiniteStreamRecognize.java b/speech/cloud-client/src/main/java/com/example/speech/InfiniteStreamRecognize.java index 7844e23af5e..c281c298da9 100644 --- a/speech/cloud-client/src/main/java/com/example/speech/InfiniteStreamRecognize.java +++ b/speech/cloud-client/src/main/java/com/example/speech/InfiniteStreamRecognize.java @@ -20,14 +20,17 @@ import com.google.api.gax.rpc.ClientStream; import com.google.api.gax.rpc.ResponseObserver; import com.google.api.gax.rpc.StreamController; -import com.google.cloud.speech.v1.RecognitionConfig; -import com.google.cloud.speech.v1.SpeechClient; -import com.google.cloud.speech.v1.SpeechRecognitionAlternative; -import com.google.cloud.speech.v1.StreamingRecognitionConfig; -import com.google.cloud.speech.v1.StreamingRecognitionResult; -import com.google.cloud.speech.v1.StreamingRecognizeRequest; -import com.google.cloud.speech.v1.StreamingRecognizeResponse; +import com.google.cloud.speech.v1p1beta1.RecognitionConfig; +import com.google.cloud.speech.v1p1beta1.SpeechClient; +import com.google.cloud.speech.v1p1beta1.SpeechRecognitionAlternative; +import com.google.cloud.speech.v1p1beta1.StreamingRecognitionConfig; +import com.google.cloud.speech.v1p1beta1.StreamingRecognitionResult; +import com.google.cloud.speech.v1p1beta1.StreamingRecognizeRequest; +import com.google.cloud.speech.v1p1beta1.StreamingRecognizeResponse; import com.google.protobuf.ByteString; +import com.google.protobuf.Duration; +import java.lang.Math; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -39,11 +42,29 @@ public class InfiniteStreamRecognize { + private static final int STREAMING_LIMIT = 10000; // 10 seconds + + public static final String RED = "\033[0;31m"; + public static final String GREEN = "\033[0;32m"; + public static final String YELLOW = "\033[0;33m"; + // Creating shared object private static volatile BlockingQueue sharedQueue = new LinkedBlockingQueue(); private static TargetDataLine targetDataLine; private static int BYTES_PER_BUFFER = 6400; // buffer size in bytes + private static int restartCounter = 0; + private static ArrayList audioInput = new ArrayList(); + private static ArrayList lastAudioInput = new ArrayList(); + private static int resultEndTimeInMS = 0; + private static int isFinalEndTime = 0; + private static int finalRequestEndTime = 0; + private static boolean newStream = true; + private static double bridgingOffset = 0; + private static boolean lastTranscriptWasFinal = false; + private static StreamController referenceToStreamController; + private static ByteString tempByteString; + public static void main(String... args) { try { infiniteStreamingRecognize(); @@ -60,6 +81,7 @@ class MicBuffer implements Runnable { @Override public void run() { + System.out.println(YELLOW); System.out.println("Start speaking...Press Ctrl-C to stop"); targetDataLine.start(); byte[] data = new byte[BYTES_PER_BUFFER]; @@ -88,24 +110,48 @@ public void run() { ArrayList responses = new ArrayList<>(); - public void onStart(StreamController controller) {} + public void onStart(StreamController controller) { + referenceToStreamController = controller; + } public void onResponse(StreamingRecognizeResponse response) { + responses.add(response); + StreamingRecognitionResult result = response.getResultsList().get(0); - // There can be several alternative transcripts for a given chunk of speech. Just - // use the first (most likely) one here. + + Duration resultEndTime = result.getResultEndTime(); + + resultEndTimeInMS = (int) ((resultEndTime.getSeconds() * 1000) + + (resultEndTime.getNanos() / 1000000)); + + double correctedTime = resultEndTimeInMS - bridgingOffset + + (STREAMING_LIMIT * restartCounter); + DecimalFormat format = new DecimalFormat("0.#"); + SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0); - System.out.printf("Transcript : %s\n", alternative.getTranscript()); - } + if (result.getIsFinal()) { + System.out.print(GREEN); + System.out.print("\033[2K\r"); + System.out.printf("%s: %s\n", format.format(correctedTime), + alternative.getTranscript()); - public void onComplete() { - System.out.println("Done"); - } + isFinalEndTime = resultEndTimeInMS; + lastTranscriptWasFinal = true; + } else { + System.out.print(RED); + System.out.print("\033[2K\r"); + System.out.printf("%s: %s", format.format(correctedTime), + alternative.getTranscript()); - public void onError(Throwable t) { - System.out.println(t); + lastTranscriptWasFinal = false; + } } + + public void onComplete() {} + + public void onError(Throwable t) {} + }; clientStream = client.streamingRecognizeCallable().splitCall(responseObserver); @@ -116,8 +162,12 @@ public void onError(Throwable t) { .setLanguageCode("en-US") .setSampleRateHertz(16000) .build(); + StreamingRecognitionConfig streamingRecognitionConfig = - StreamingRecognitionConfig.newBuilder().setConfig(recognitionConfig).build(); + StreamingRecognitionConfig.newBuilder() + .setConfig(recognitionConfig) + .setInterimResults(true) + .build(); StreamingRecognizeRequest request = StreamingRecognizeRequest.newBuilder() @@ -151,9 +201,28 @@ public void onError(Throwable t) { long estimatedTime = System.currentTimeMillis() - startTime; - if (estimatedTime >= 55000) { + if (estimatedTime >= STREAMING_LIMIT) { clientStream.closeSend(); + referenceToStreamController.cancel(); // remove Observer + + if (resultEndTimeInMS > 0) { + finalRequestEndTime = isFinalEndTime; + } + resultEndTimeInMS = 0; + + lastAudioInput = null; + lastAudioInput = audioInput; + audioInput = new ArrayList(); + + restartCounter++; + + if (!lastTranscriptWasFinal) { + System.out.print('\n'); + } + + newStream = true; + clientStream = client.streamingRecognizeCallable().splitCall(responseObserver); request = @@ -161,13 +230,55 @@ public void onError(Throwable t) { .setStreamingConfig(streamingRecognitionConfig) .build(); + System.out.println(YELLOW); + System.out.printf("%d: RESTARTING REQUEST\n", restartCounter * STREAMING_LIMIT); + startTime = System.currentTimeMillis(); } else { + + if ((newStream) && (lastAudioInput.size() > 0)) { + // if this is the first audio from a new request + // calculate amount of unfinalized audio from last request + // resend the audio to the speech client before incoming audio + double chunkTime = STREAMING_LIMIT / lastAudioInput.size(); + // ms length of each chunk in previous request audio arrayList + if (chunkTime != 0) { + if (bridgingOffset < 0) { + // bridging Offset accounts for time of resent audio + // calculated from last request + bridgingOffset = 0; + } + if (bridgingOffset > finalRequestEndTime) { + bridgingOffset = finalRequestEndTime; + } + int chunksFromMS = (int) Math.floor((finalRequestEndTime + - bridgingOffset) / chunkTime); + // chunks from MS is number of chunks to resend + bridgingOffset = (int) Math.floor((lastAudioInput.size() + - chunksFromMS) * chunkTime); + // set bridging offset for next request + for (int i = chunksFromMS; i < lastAudioInput.size(); i++) { + + request = + StreamingRecognizeRequest.newBuilder() + .setAudioContent(lastAudioInput.get(i)) + .build(); + clientStream.send(request); + } + } + newStream = false; + } + + tempByteString = ByteString.copyFrom(sharedQueue.take()); + request = StreamingRecognizeRequest.newBuilder() - .setAudioContent(ByteString.copyFrom(sharedQueue.take())) + .setAudioContent(tempByteString) .build(); + + audioInput.add(tempByteString); + } clientStream.send(request); diff --git a/speech/cloud-client/src/main/java/com/example/speech/Recognize.java b/speech/cloud-client/src/main/java/com/example/speech/Recognize.java index d8845d499be..0797e8211d0 100644 --- a/speech/cloud-client/src/main/java/com/example/speech/Recognize.java +++ b/speech/cloud-client/src/main/java/com/example/speech/Recognize.java @@ -699,7 +699,6 @@ public void onError(Throwable t) { System.out.println("Stop speaking."); targetDataLine.stop(); targetDataLine.close(); - break; } request = StreamingRecognizeRequest.newBuilder() diff --git a/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java b/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java index 2eef6f05807..0aa8db5d2ca 100644 --- a/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java +++ b/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java @@ -113,22 +113,22 @@ public void testStreamRecognize() throws Exception { @Test public void testAutoPunctuation() throws Exception { Recognize.transcribeFileWithAutomaticPunctuation(audioFileName); - String got = bout.toString(); - assertThat(got).contains("How old is the Brooklyn Bridge?"); + String got = bout.toString().toLowerCase(); + assertThat(got).contains("how old is the brooklyn bridge"); } @Test public void testGcsAutoPunctuation() throws Exception { Recognize.transcribeGcsWithAutomaticPunctuation(gcsAudioPath); - String got = bout.toString(); - assertThat(got).contains("How old is the Brooklyn Bridge?"); + String got = bout.toString().toLowerCase(); + assertThat(got).contains("how old is the brooklyn bridge"); } @Test public void testStreamAutoPunctuation() throws Exception { Recognize.streamingTranscribeWithAutomaticPunctuation(audioFileName); - String got = bout.toString(); - assertThat(got).contains("How old is the Brooklyn Bridge?"); + String got = bout.toString().toLowerCase(); + assertThat(got).contains("how old is the brooklyn bridge"); } @Test From 46821aa7c3ecd73b3fa5d92c676ef193ad7ceadc Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 17 May 2019 12:39:55 -0700 Subject: [PATCH 30/49] Update app engine plugin and readmes for Java 11 (#1424) * Update plugin * Update ReadMes --- appengine-java11/README.md | 5 ----- appengine-java11/appengine-simple-jetty-main/README.md | 5 +++++ appengine-java11/custom-entrypoint/README.md | 2 +- appengine-java11/gaeinfo/pom.xml | 2 +- appengine-java11/guestbook-cloud-firestore/pom.xml | 2 +- appengine-java11/http-server/README.md | 2 +- appengine-java11/http-server/pom.xml | 2 +- appengine-java11/kotlin-ktor/pom.xml | 2 +- appengine-java11/micronaut-helloworld/pom.xml | 2 +- appengine-java11/oauth2/pom.xml | 2 +- appengine-java11/quarkus-helloworld/pom.xml | 2 +- appengine-java11/spanner/pom.xml | 2 +- appengine-java11/sparkjava-helloworld/pom.xml | 2 +- appengine-java11/springboot-helloworld/pom.xml | 2 +- appengine-java11/tasks-handler/pom.xml | 2 +- appengine-java11/tasks/README.md | 2 +- appengine-java11/vertx-helloworld/README.md | 2 +- appengine-java11/vertx-helloworld/pom.xml | 2 +- 18 files changed, 21 insertions(+), 21 deletions(-) create mode 100644 appengine-java11/appengine-simple-jetty-main/README.md diff --git a/appengine-java11/README.md b/appengine-java11/README.md index 3505746bec9..a84d7c24171 100644 --- a/appengine-java11/README.md +++ b/appengine-java11/README.md @@ -10,11 +10,6 @@ standard Java 11 environment. ## Prerequisites -**Private Alpha** -To access the Java 11 Google App Engine standard runtime, you'll need to apply -to become part of the App Engine [Alpha program](https://docs.google.com/forms/d/e/1FAIpQLSf5uE5eknJjFEmcVBI6sMitBU0QQ1LX_J7VrA_OTQabo6EEEw/viewform). - - ### Download Maven These samples use the [Apache Maven][maven] build system. Before getting 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..1b01e9e1e66 --- /dev/null +++ b/appengine-java11/appengine-simple-jetty-main/README.md @@ -0,0 +1,5 @@ +# Embedded Jetty Server for running WAR files on Google App Engine Standard with Java 11 + +This sample demonstrates an embedded Jetty server which instantiates an HTTP server to run a 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). diff --git a/appengine-java11/custom-entrypoint/README.md b/appengine-java11/custom-entrypoint/README.md index d219f6a674d..dab91209694 100644 --- a/appengine-java11/custom-entrypoint/README.md +++ b/appengine-java11/custom-entrypoint/README.md @@ -1,4 +1,4 @@ -# Hello World App for Google App Engine Standard with Java 11 +# 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 diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml index fd106c685a8..bff2bbb14bc 100644 --- a/appengine-java11/gaeinfo/pom.xml +++ b/appengine-java11/gaeinfo/pom.xml @@ -124,7 +124,7 @@ Copyright 2019 Google LLC com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 gaeinfo diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml index 025b22dcaca..f4606c330c8 100644 --- a/appengine-java11/guestbook-cloud-firestore/pom.xml +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -80,7 +80,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 guestbook diff --git a/appengine-java11/http-server/README.md b/appengine-java11/http-server/README.md index c2ee758a48b..c49165328be 100644 --- a/appengine-java11/http-server/README.md +++ b/appengine-java11/http-server/README.md @@ -1,4 +1,4 @@ -# Single Fat Jar Application on Google App Engine Standard with Java 11 +# 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), diff --git a/appengine-java11/http-server/pom.xml b/appengine-java11/http-server/pom.xml index 8a8f34d2bb5..2a059349a70 100644 --- a/appengine-java11/http-server/pom.xml +++ b/appengine-java11/http-server/pom.xml @@ -37,7 +37,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 http-server diff --git a/appengine-java11/kotlin-ktor/pom.xml b/appengine-java11/kotlin-ktor/pom.xml index a772fd62b41..3a2a4d23608 100644 --- a/appengine-java11/kotlin-ktor/pom.xml +++ b/appengine-java11/kotlin-ktor/pom.xml @@ -165,7 +165,7 @@ limitations under the License. com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 kotlin-ktor diff --git a/appengine-java11/micronaut-helloworld/pom.xml b/appengine-java11/micronaut-helloworld/pom.xml index 8c09925169a..dfdb821c8c6 100644 --- a/appengine-java11/micronaut-helloworld/pom.xml +++ b/appengine-java11/micronaut-helloworld/pom.xml @@ -112,7 +112,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 micronaut-helloworld diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml index bb0f3631e8f..a4592d752e6 100644 --- a/appengine-java11/oauth2/pom.xml +++ b/appengine-java11/oauth2/pom.xml @@ -98,7 +98,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 oauth2 diff --git a/appengine-java11/quarkus-helloworld/pom.xml b/appengine-java11/quarkus-helloworld/pom.xml index 6c6d3a941d1..dd84fe268cb 100644 --- a/appengine-java11/quarkus-helloworld/pom.xml +++ b/appengine-java11/quarkus-helloworld/pom.xml @@ -99,7 +99,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 quarkus-helloworld diff --git a/appengine-java11/spanner/pom.xml b/appengine-java11/spanner/pom.xml index 6eb08637832..93c97fb371e 100644 --- a/appengine-java11/spanner/pom.xml +++ b/appengine-java11/spanner/pom.xml @@ -96,7 +96,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 spanner diff --git a/appengine-java11/sparkjava-helloworld/pom.xml b/appengine-java11/sparkjava-helloworld/pom.xml index 8e5fd5e58ab..7492298dbbb 100644 --- a/appengine-java11/sparkjava-helloworld/pom.xml +++ b/appengine-java11/sparkjava-helloworld/pom.xml @@ -101,7 +101,7 @@ limitations under the License. com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 ${project.build.directory}/sparkjava-helloworld-1.0-jar-with-dependencies.jar sparkjava-helloworld diff --git a/appengine-java11/springboot-helloworld/pom.xml b/appengine-java11/springboot-helloworld/pom.xml index ef6d11efc08..f14f5696bad 100644 --- a/appengine-java11/springboot-helloworld/pom.xml +++ b/appengine-java11/springboot-helloworld/pom.xml @@ -92,7 +92,7 @@ com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 springboot-helloworld diff --git a/appengine-java11/tasks-handler/pom.xml b/appengine-java11/tasks-handler/pom.xml index 23b4920c450..048629e4c63 100644 --- a/appengine-java11/tasks-handler/pom.xml +++ b/appengine-java11/tasks-handler/pom.xml @@ -96,7 +96,7 @@ limitations under the License. com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 task-handler diff --git a/appengine-java11/tasks/README.md b/appengine-java11/tasks/README.md index daacf062b4b..5f8837790ab 100644 --- a/appengine-java11/tasks/README.md +++ b/appengine-java11/tasks/README.md @@ -28,7 +28,7 @@ App Engine task attempts. To create a queue using the Cloud SDK, use the following gcloud command: ``` -gcloud beta tasks queues create-app-engine-queue my-appengine-queue +gcloud beta tasks queues create my-appengine-queue ``` Note: A newly created queue will route to the default App Engine service and diff --git a/appengine-java11/vertx-helloworld/README.md b/appengine-java11/vertx-helloworld/README.md index d1945fac520..a7571eb42ca 100644 --- a/appengine-java11/vertx-helloworld/README.md +++ b/appengine-java11/vertx-helloworld/README.md @@ -1,4 +1,4 @@ -# Vertx Application on Google App Engine Standard with Java 11 +# 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. diff --git a/appengine-java11/vertx-helloworld/pom.xml b/appengine-java11/vertx-helloworld/pom.xml index 95d413aa879..c5637c6d94a 100644 --- a/appengine-java11/vertx-helloworld/pom.xml +++ b/appengine-java11/vertx-helloworld/pom.xml @@ -97,7 +97,7 @@ limitations under the License. com.google.cloud.tools appengine-maven-plugin - 2.0.0-rc6 + 2.0.0 ${project.build.directory}/vertx-hello-j11-1.0-jar-with-dependencies.jar vertx-hello-java11 From 144784a901883f368f7997c483078e2f6339437d Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 17 May 2019 12:47:40 -0700 Subject: [PATCH 31/49] Add Cloud Sql sample for Java 11 (#1414) * Add Cloud Sql sample * Add comments to pom * Update pom * Update cloudsql sample for Java 11 --- appengine-java11/cloudsql/README.md | 72 ++++++++++++++ appengine-java11/cloudsql/app.yaml | 23 +++++ appengine-java11/cloudsql/pom.xml | 146 ++++++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 appengine-java11/cloudsql/README.md create mode 100644 appengine-java11/cloudsql/app.yaml create mode 100644 appengine-java11/cloudsql/pom.xml 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..f2c650c3078 --- /dev/null +++ b/appengine-java11/cloudsql/pom.xml @@ -0,0 +1,146 @@ + + + + 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 + + + + + From 827291acbce1c999763bf8bf214a99414e483406 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Mon, 20 May 2019 13:08:03 -0700 Subject: [PATCH 32/49] Update ReadMe and comments (#1426) --- .../src/main/java/com/example/guestbook/Greeting.java | 2 +- .../src/main/java/com/example/guestbook/Guestbook.java | 10 +++++----- .../src/main/webapp/index.jsp | 4 ++-- appengine-java11/oauth2/README.md | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) 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 index e1fb8b22e19..df7872751e1 100644 --- 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 @@ -22,7 +22,7 @@ import java.util.Map; import java.util.Objects; -/** Greeting model. */ +/** Represents a greeting: id, guestbook reference, author, content, date. */ @SuppressWarnings("JavadocMethod") public class Greeting { 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 index ee33af8c39c..d7932c8166f 100644 --- 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 @@ -30,7 +30,7 @@ import java.util.Map; import java.util.Objects; -/** Guestbook model. */ +/** Represents a guestbook: book name, book document reference. */ @SuppressWarnings("JavadocMethod") public class Guestbook { @@ -42,24 +42,24 @@ public class Guestbook { 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] - // Get Guestbook reference in the collection. + // The Guestbook document reference in the collection. bookRef = getFirestore().collection("Guestbooks").document(this.book); - // Add Guestbook to collection. + // 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] - /** Get greetings for the Guestbook */ + /** Query Firstore for Guestbook greetings */ public List getGreetings() { // Initialize a List for Greetings. ImmutableList.Builder greetings = new ImmutableList.Builder(); diff --git a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp index 1e7224573e4..9b5bfa84e4f 100644 --- a/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp +++ b/appengine-java11/guestbook-cloud-firestore/src/main/webapp/index.jsp @@ -35,10 +35,10 @@ limitations under the License. } pageContext.setAttribute("guestbookName", guestbookName); - // Create the correct Ancestor key + // Create a Guestbook object. Guestbook theBook = new Guestbook(guestbookName); - // Run an ancestor query to ensure we see the most up-to-date + // 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(); %> diff --git a/appengine-java11/oauth2/README.md b/appengine-java11/oauth2/README.md index 02e42d1c933..05433527f9f 100644 --- a/appengine-java11/oauth2/README.md +++ b/appengine-java11/oauth2/README.md @@ -1,7 +1,7 @@ # 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 +[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. From b6dd6a754e18ffd84174bf5622d6bd6679b2f1f7 Mon Sep 17 00:00:00 2001 From: Angela Funk <32649053+angelafunk@users.noreply.github.com> Date: Mon, 20 May 2019 13:20:04 -0700 Subject: [PATCH 33/49] add region tag (#1427) * add region tag * Update app.yaml --- appengine-java11/http-server/src/main/appengine/app.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appengine-java11/http-server/src/main/appengine/app.yaml b/appengine-java11/http-server/src/main/appengine/app.yaml index 8848aeed6c3..22c1d8e31f5 100644 --- a/appengine-java11/http-server/src/main/appengine/app.yaml +++ b/appengine-java11/http-server/src/main/appengine/app.yaml @@ -12,5 +12,7 @@ # 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] From 6272255fa5c79c463bdd2058f9c81bb8fac78569 Mon Sep 17 00:00:00 2001 From: Noah Negrey Date: Tue, 21 May 2019 10:04:57 -0700 Subject: [PATCH 34/49] Revert Tests, product team rolled back changes, Auto Punctuation behavior is back to the expected output (#1428) --- .../test/java/com/example/speech/RecognizeIT.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java b/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java index 0aa8db5d2ca..2eef6f05807 100644 --- a/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java +++ b/speech/cloud-client/src/test/java/com/example/speech/RecognizeIT.java @@ -113,22 +113,22 @@ public void testStreamRecognize() throws Exception { @Test public void testAutoPunctuation() throws Exception { Recognize.transcribeFileWithAutomaticPunctuation(audioFileName); - String got = bout.toString().toLowerCase(); - assertThat(got).contains("how old is the brooklyn bridge"); + String got = bout.toString(); + assertThat(got).contains("How old is the Brooklyn Bridge?"); } @Test public void testGcsAutoPunctuation() throws Exception { Recognize.transcribeGcsWithAutomaticPunctuation(gcsAudioPath); - String got = bout.toString().toLowerCase(); - assertThat(got).contains("how old is the brooklyn bridge"); + String got = bout.toString(); + assertThat(got).contains("How old is the Brooklyn Bridge?"); } @Test public void testStreamAutoPunctuation() throws Exception { Recognize.streamingTranscribeWithAutomaticPunctuation(audioFileName); - String got = bout.toString().toLowerCase(); - assertThat(got).contains("how old is the brooklyn bridge"); + String got = bout.toString(); + assertThat(got).contains("How old is the Brooklyn Bridge?"); } @Test From 76be7a7c5f23f072545a35fba568e48369644091 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Tue, 21 May 2019 14:01:39 -0700 Subject: [PATCH 35/49] Cloud Spanner: Specify the name for packaging the JAR (#1430) * Cloud Spanner: Allow version overrides on the command line. --- spanner/cloud-client/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/spanner/cloud-client/pom.xml b/spanner/cloud-client/pom.xml index 04bb822df22..e1a76d688c1 100644 --- a/spanner/cloud-client/pom.xml +++ b/spanner/cloud-client/pom.xml @@ -140,6 +140,7 @@ limitations under the License. + spanner-google-cloud-samples maven-assembly-plugin From 4fc43b744001f00393a22578866f1ff4c7e591dd Mon Sep 17 00:00:00 2001 From: aman-ebay Date: Wed, 22 May 2019 10:55:49 -0700 Subject: [PATCH 36/49] Update LookupEntryBigQueryDataset.java (#1434) --- .../com/example/datacatalog/LookupEntryBigQueryDataset.java | 2 ++ 1 file changed, 2 insertions(+) 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 index b81737645fc..4c4ee950d06 100644 --- a/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java +++ b/datacatalog/cloud-client/src/main/java/com/example/datacatalog/LookupEntryBigQueryDataset.java @@ -16,6 +16,7 @@ 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; @@ -54,3 +55,4 @@ public static void lookupEntry(String projectId, String datasetId) { } } } +// [END datacatalog_bigquery_lookup_dataset] From a7e39e774e3d3fdd29046e8d5235b2fdfcbe72ff Mon Sep 17 00:00:00 2001 From: Billy Jacobson Date: Wed, 22 May 2019 22:36:43 -0400 Subject: [PATCH 37/49] Moving Bigtable samples into this repo (#1429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Setup mvn package and copy in existing samples and tests * Fix style issues and ran tests * Updating pom with current versions * Adding default values for the system propertiesĖ† * surefire instead of failsafe --- bigtable/pom.xml | 115 ++++++ .../com/m/examples/bigtable/HelloWorld.java | 187 +++++++++ .../bigtable/InstanceAdminExample.java | 215 ++++++++++ .../examples/bigtable/TableAdminExample.java | 385 ++++++++++++++++++ .../m/examples/bigtable/HelloWorldTest.java | 151 +++++++ .../bigtable/InstanceAdminExampleTest.java | 153 +++++++ .../bigtable/TableAdminExampleTest.java | 227 +++++++++++ 7 files changed, 1433 insertions(+) create mode 100644 bigtable/pom.xml create mode 100644 bigtable/src/main/java/com/m/examples/bigtable/HelloWorld.java create mode 100644 bigtable/src/main/java/com/m/examples/bigtable/InstanceAdminExample.java create mode 100644 bigtable/src/main/java/com/m/examples/bigtable/TableAdminExample.java create mode 100644 bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java create mode 100644 bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java create mode 100644 bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java diff --git a/bigtable/pom.xml b/bigtable/pom.xml new file mode 100644 index 00000000000..b9570dffeb9 --- /dev/null +++ b/bigtable/pom.xml @@ -0,0 +1,115 @@ + + + + 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 + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + + java-docs-samples-testing + instance + + + + + + + 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/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..e19a1a17e66 --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java @@ -0,0 +1,151 @@ +/* + * 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 PROJECT_PROPERTY_NAME = "bigtable.project"; + private static final String INSTANCE_PROPERTY_NAME = "bigtable.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; + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = System.getProperty(PROJECT_PROPERTY_NAME); + instanceId = System.getProperty(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 { + if (adminClient == null || dataClient == null) { + throw new AssumptionViolatedException( + PROJECT_PROPERTY_NAME + + " or " + + INSTANCE_PROPERTY_NAME + + " property is not set, skipping integration tests."); + } + 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..8a92449ba74 --- /dev/null +++ b/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java @@ -0,0 +1,153 @@ +/* + * 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 PROJECT_PROPERTY_NAME = "bigtable.project"; + 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; + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = System.getProperty(PROJECT_PROPERTY_NAME); + 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 { + if (adminClient == null) { + throw new AssumptionViolatedException( + PROJECT_PROPERTY_NAME + " property is not set, skipping integration tests."); + } + 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/TableAdminExampleTest.java b/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java new file mode 100644 index 00000000000..d2163bf691a --- /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.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 PROJECT_PROPERTY_NAME = "bigtable.project"; + private static final String INSTANCE_PROPERTY_NAME = "bigtable.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; + + @BeforeClass + public static void beforeClass() throws IOException { + projectId = System.getProperty(PROJECT_PROPERTY_NAME); + instanceId = System.getProperty(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 { + if (adminClient == null) { + throw new AssumptionViolatedException( + INSTANCE_PROPERTY_NAME + + " or " + + PROJECT_PROPERTY_NAME + + " property is not set, skipping integration tests."); + } + 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); + } + } +} From 788979da174b99417c4eba542ec5eacf03d1c792 Mon Sep 17 00:00:00 2001 From: Billy Jacobson Date: Thu, 23 May 2019 11:32:30 -0400 Subject: [PATCH 38/49] Removing unused region tags (#1393) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Removing unused region tags * updating example region tagĖ† * Rename tests to match new format * Changing system properties for tests --- .../main/java/com/example/bigtable/BigtableHelloWorld.java | 7 +++---- .../src/main/java/com/example/bigtable/BigtableHelper.java | 4 ++-- .../bigtable/src/main/webapp/WEB-INF/appengine-web.xml | 2 -- ...igtableHelloWorld.java => BigtableHelloWorldTests.java} | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) rename appengine-java8/bigtable/src/test/java/com/example/bigtable/{ITBigtableHelloWorld.java => BigtableHelloWorldTests.java} (93%) 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; From 42df115345b0eda78d1ce81abbc9b2ff6d84e181 Mon Sep 17 00:00:00 2001 From: Dane Zeke Liergaard Date: Thu, 23 May 2019 09:34:18 -0700 Subject: [PATCH 39/49] Add Healthcare samples for Dataset operations. (#1372) * Add Healthcare samples for Dataset operations. --- .../v1beta1/DicomStoreSearchInstances.ps1 | 22 ++ .../v1beta1/dicom-store-search-instances.sh | 18 ++ healthcare/v1beta1/pom.xml | 69 +++++ .../healthcare/datasets/DatasetCreate.java | 102 ++++++++ .../datasets/DatasetDeIdentify.java | 111 ++++++++ .../healthcare/datasets/DatasetDelete.java | 74 ++++++ .../healthcare/datasets/DatasetGet.java | 75 ++++++ .../datasets/DatasetGetIamPolicy.java | 76 ++++++ .../healthcare/datasets/DatasetList.java | 99 +++++++ .../healthcare/datasets/DatasetPatch.java | 88 +++++++ .../datasets/DatasetSetIamPolicy.java | 88 +++++++ .../healthcare/dicom/DicomStoreCreate.java | 90 +++++++ .../healthcare/dicom/DicomStoreDelete.java | 76 ++++++ .../healthcare/dicom/DicomStoreExport.java | 108 ++++++++ .../healthcare/dicom/DicomStoreGet.java | 77 ++++++ .../dicom/DicomStoreGetIamPolicy.java | 77 ++++++ .../healthcare/dicom/DicomStoreImport.java | 109 ++++++++ .../healthcare/dicom/DicomStoreList.java | 100 +++++++ .../healthcare/dicom/DicomStorePatch.java | 93 +++++++ .../dicom/DicomStoreSetIamPolicy.java | 95 +++++++ .../healthcare/dicom/DicomWebDeleteStudy.java | 83 ++++++ .../dicom/DicomWebRetrieveStudy.java | 98 +++++++ .../dicom/DicomWebSearchForInstances.java | 82 ++++++ .../dicom/DicomWebStoreInstance.java | 121 +++++++++ .../healthcare/fhir/FhirStoreCreate.java | 91 +++++++ .../healthcare/fhir/FhirStoreDelete.java | 76 ++++++ .../fhir/FhirStoreExecuteBundle.java | 116 ++++++++ .../healthcare/fhir/FhirStoreExport.java | 104 ++++++++ .../healthcare/fhir/FhirStoreGet.java | 77 ++++++ .../fhir/FhirStoreGetIamPolicy.java | 77 ++++++ .../healthcare/fhir/FhirStoreImport.java | 108 ++++++++ .../healthcare/fhir/FhirStoreList.java | 102 ++++++++ .../healthcare/fhir/FhirStorePatch.java | 95 +++++++ .../fhir/FhirStoreSetIamPolicy.java | 95 +++++++ .../FhirResourceConditionalDelete.java | 83 ++++++ .../FhirResourceConditionalPatch.java | 124 +++++++++ .../FhirResourceConditionalUpdate.java | 121 +++++++++ .../fhir/resources/FhirResourceCreate.java | 118 +++++++++ .../fhir/resources/FhirResourceDelete.java | 116 ++++++++ .../resources/FhirResourceDeletePurge.java | 116 ++++++++ .../fhir/resources/FhirResourceGet.java | 111 ++++++++ .../resources/FhirResourceGetHistory.java | 114 ++++++++ .../resources/FhirResourceGetMetadata.java | 79 ++++++ .../FhirResourceGetPatientEverything.java | 115 ++++++++ .../fhir/resources/FhirResourcePatch.java | 118 +++++++++ .../fhir/resources/FhirResourceSearch.java | 115 ++++++++ .../resources/FhirResourceSearchPost.java | 120 +++++++++ .../healthcare/hl7v2/Hl7v2StoreCreate.java | 92 +++++++ .../healthcare/hl7v2/Hl7v2StoreDelete.java | 76 ++++++ .../healthcare/hl7v2/Hl7v2StoreGet.java | 77 ++++++ .../hl7v2/Hl7v2StoreGetIamPolicy.java | 77 ++++++ .../healthcare/hl7v2/Hl7v2StoreList.java | 100 +++++++ .../healthcare/hl7v2/Hl7v2StorePatch.java | 94 +++++++ .../hl7v2/Hl7v2StoreSetIamPolicy.java | 96 +++++++ .../hl7v2/messages/HL7v2MessageCreate.java | 97 +++++++ .../hl7v2/messages/HL7v2MessageDelete.java | 78 ++++++ .../hl7v2/messages/HL7v2MessageGet.java | 78 ++++++ .../hl7v2/messages/HL7v2MessageIngest.java | 97 +++++++ .../hl7v2/messages/HL7v2MessageList.java | 102 ++++++++ .../hl7v2/messages/HL7v2MessagePatch.java | 99 +++++++ .../snippets/healthcare/DatasetTests.java | 149 +++++++++++ .../healthcare/DicomStoreStudyTests.java | 140 ++++++++++ .../snippets/healthcare/DicomStoreTests.java | 181 +++++++++++++ .../healthcare/FhirResourceTests.java | 247 ++++++++++++++++++ .../snippets/healthcare/FhirStoreTests.java | 192 ++++++++++++++ .../healthcare/Hl7v2MessageTests.java | 169 ++++++++++++ .../snippets/healthcare/Hl7v2StoreTests.java | 146 +++++++++++ .../java/snippets/healthcare/TestBase.java | 86 ++++++ .../test/resources/hl7v2-sample-ingest.txt | 1 + .../v1beta1/src/test/resources/jpeg_text.dcm | Bin 0 -> 10656 bytes 70 files changed, 6896 insertions(+) create mode 100644 healthcare/v1beta1/DicomStoreSearchInstances.ps1 create mode 100644 healthcare/v1beta1/dicom-store-search-instances.sh create mode 100644 healthcare/v1beta1/pom.xml create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDeIdentify.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetGetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetList.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetPatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/datasets/DatasetSetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreExport.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreGetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreImport.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreList.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStorePatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomStoreSetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebDeleteStudy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebRetrieveStudy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebSearchForInstances.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/dicom/DicomWebStoreInstance.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExecuteBundle.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreExport.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreGetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreList.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStorePatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreSetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalPatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceConditionalUpdate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceDeletePurge.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetHistory.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetMetadata.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceGetPatientEverything.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourcePatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/resources/FhirResourceSearchPost.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreGetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreList.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StorePatch.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/Hl7v2StoreSetIamPolicy.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageCreate.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageDelete.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageGet.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageIngest.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessageList.java create mode 100644 healthcare/v1beta1/src/main/java/snippets/healthcare/hl7v2/messages/HL7v2MessagePatch.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/DatasetTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreStudyTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/DicomStoreTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/FhirResourceTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/FhirStoreTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2MessageTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/Hl7v2StoreTests.java create mode 100644 healthcare/v1beta1/src/test/java/snippets/healthcare/TestBase.java create mode 100644 healthcare/v1beta1/src/test/resources/hl7v2-sample-ingest.txt create mode 100644 healthcare/v1beta1/src/test/resources/jpeg_text.dcm 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..b746b009a4a --- /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_delete_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_delete_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..0323e2c59c8 --- /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_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.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_instance] 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 0000000000000000000000000000000000000000..950fb16166c15689d5f0b8d0751a041dec2beff2 GIT binary patch literal 10656 zcmc(FWmuF!*Z)oKf^;`4tTae0EX`8VtaKv+5-TmaG$;}Z0)m8;(%m5`k^<70fEG8i#CMF4&k`k5>lM)jbg~8zx zlHy{x0N#H&{}|#TQWByPFmYkHsIY{nxP-8zsDz}Xl&~;dOadk%E((W9;sO-696CTm zNK{A?CM+Z(EG#T3^sfaI5*Nk=sBTe;|DdAxSY2FhKX; z75^W#1Op8J<@_JDgaD-f<%o$13yX*f!{MT0Fkvwlb6OojFNs39`8dF3{Oc*95Dt@b!n1r~nqzGID4i|%oO2K*leKmuBUy=vF zzqJMlpo7#!Dy!=wbyP(mJpXKcivl=20OkKm0M5TY@GS%9eDxwpriXs`a{yB|@cMCs0l@#JR=8D8BUVO| z5IyyMSnvB}cD=+in(iS=h$mv6Be);MF}^>!Ou~ZoVJN)Q;db#pv^^0 z{;piG^>J_bZz;A#=ZAkng12!7V%Ey176&Yk_S3UmvZX&d!s!_8khgc#@30Uj%0`|W%2th@O{L+JX_QPIU5pWfR}^V}%)vb6 zk0lq>fe{|Lz)1npeD7Zlx%lv+QyT4L;n1sMob64uVV`28*wRb=z#zjk>aLHi-gI&# z524!Fk}&}Mp$k`XwMcJvm9qf{!kXW!+eJn2AiV2}luGV1TldHN2rzJxH$M?*1RFdn z?c=h=zleRAr||RPfLU~LA&BEc6510tEXB2EghI|Tx!=Ede3Wu251)63uyE-rL0P-5 zz9(pKHG4*UXqalc(N_+ah^t*9{rIQ{QySGjQB_elUP=1#^ajwxnuaRLssVJ2JsJ(nSCaNG&D{>}>%1OqiSGP5<8pESmUs-Mpb~_P zl^w$UW_|+_eiTrp^cTuTBrRIF!lEs@7z@u8{hz6@tR9?C96XQ_M9T; zj%k79L4b`bFXnh4;|+I_W+qaO6O${d$fX0`^Z&pF@e1L~u)myIOXsYhCWx8uq6IdI zE-nq@p-1vlAlBDnKKjtu?meG%Cqiz1O!gSv=mcWaF{qOVGBk9h_Ai2tq zmA>zu4%_t(DS<2PRuw+@{XTnFFOU}il2=_~J{BJmXXTX99CUHH)JheK|Hcurgnd3v zDaWV6z&3@HO`gxmpx)vi)6tcP(7_G1;z)l9JnL^)vgwW>4?)G=TH#X7+9|@{I&4ao zO(h$PJ4i{b5|d-n6FBxWmhz4^MdLKWPh`c1>r+#>eEi0aamBXuR*)rcO1+9q>>k=7 zq41aF)5t|p!ROtatX>$eV0GDqHpF2h7gG+Mc5r?ev<$Yxj~*`}nu(=xai)npT54S-?w z4}}aOh0v}v&Zb^oe8gr+p{_+nEsZQ5M}F2gRUk1R4n$aFDTW`2d4rxvGL71w$X!w2 z9ToSB~|>GeR97b?GvGRmW5Tls1H3bU#n74)j8rL+?%Ml#R@{H zHZ?PBlZVt_DLyRJQSLDGcn(fpDiK)zQGG9b2UEdU9-&t3o7ZWJFlC3yc3a^KFva6a zlHhFDa99-&S|(k=B_YTJHn0RkUT4WoYr-vV^Up-U6uP3X*t@ztSQnE zhb;NU*Z9oNXNY~$<1%O#JkZ-3gWi2r=8nQPVg|nC(dtghU8Bgg@a7wIIaHEi4jSB% zdWud9YPwv-``S5~oorL9aPVoN89qfYVhSq^t$V;yV}Q{m9Tc0)zz6)dWyUB%%MWH= zFBZO}d-iPJ4r zxM&rxSm7;ib_8^yHsxmOe9Tx)qx7XIF{RwoQ1Z#x7cvo?E0YnBFPr0gJM<wHAr}e`7vJj_Q&+ zn0`v9qdF1nX|-K_+2lJIu zo9IcYi{@nuHEZ3s)tL(d)>BxuNK)cYO3^S)xW;L96ecM#8E{2iS6v&|z{q?E!d zTe%3>?;H`=dpmHJ-@Yw@PT##px=H>JE++5i26*}7wd`9S-T89fNFD}T$TUm;X<#M8 z%yMr>*_SoyDfeAk!RKDS+!}B>fS1I6%KLrhxm!wdR;bxf@0Y1P%VpG(wcJMa-0$qn z5IcMLkvi2{crU=i~kcN4u4MvSR4kI|^T7?9oiV ztg%P{J2N(SuuqEBiD9|Fbw)Zp!3=-0ILkCV%ttc@SVPk9ox;UC&3oOYR5O237lMIBs(`Zxh&x9T3S^W<nKoSYQ=F~f%+(U45t(=tqCLfl&y`Zwyn|C5h zFQErqAeyf>gH+%xvvc|P=YIs?(-ylOw^QFJHJLyLx--^IT2qDag~xqXC~t z<2~VAHCAVh`ySErN5&kxY^m$mqRU!xkr9F@=Co*-|6vCH1(VgEh|seSx%(#>`uXxR z!bOYBAyv#9gpn+pxFn)Osiog`j1?uIg1^B82H3v676Oy9|v@BV6 z<2%I-FxT#;^4G^r)SftpgcK~)WyN^$#TDZ!Urppk1ez=L*otZ_O16e zKFXdxe(cfJle#E74rvC!VqCQpd_}rQG%oV^kMz_6-Q4`#?EAXa^6?Mfrz@R_MZ_kC zY@{~^?E=OHPW8@_0mLo-WE)usng^cQ=W?-}Qc~ZcBEuiyN%e#_H)00LL zuU0o^mHJnib}6Qicz^C$v!_)F&b5LctoZH}GzpcC50D_BNPp_z{DWH^Qp4XSOr)y4 ztA#9jd0*QZz}@Csk_H-$x6iaTN|uP+^}=k#(Uy18{anRRlD-F`MvaN6(@fXrxQymB ziNoj=?a0p*x<&jwCZ1USlSu-0JbKYSGS#D?xDVLn`))&l>h{+@E%&Cb-AG91h}NF= zQ&V&7Wki2Uc{?!aYo97qZe{Ofyczrzqevht0)|7N-mL zux=(LE+E|h39ZrS0W_NRg;L(Y)7Q+wrOCAt*~z_k-{|y5AoGbgLM`iadYnInR2IYM z-FfH8`U^ZFxg`IV0D^|-$@z^0Ojdr4oxzc?{FU=_q;-2gYA;7o__B@ELKd3(*ahBI z*}jpU{YJ8k$}nOPeH%Cr63X+&Y`1nC-!sBJnh`y=C;? zSIo@JgyT(i%nX!vd|m>}t|wnrQ|xTPZ1w^9L#|jC*gk0MCuOqPIIKuHxN>c!BBkAt zNR#7jy%~KJk7ajN$tWSTu;hnlPRWluXx&$7f8TlLu#33v4)!%YneKgS^_=#e`kP-s zb1=7i*`v_U=>h1d2gns~7ul+NNjs~!ghijQWmP}XII5oZCHRZ0M;cC8^A3i=xIf@J?g$h+eV;|z?@i$dq9pYJ_tTvh|+-PZwj8oH>}XmIl`s(NL`TrhK0B z4bam@P->dkfjNsiHyN_O3mrzHKvfDA`paooTe}RlDg!h(K+YagQAo+dy%_$r~c*4UhsdPD$=>XS4~1Pz7cX zca>==<58+lHsVuiLEmWktnw+bQRbg!PldlZCz78u`dZOmlqQ?;NNCRXh*(Xt)F>C% z*l7{rs*;uKcUn$z!FgY4O5peArVK7QrbA@_kxuG#P@STXpKxJ>h=)_N`j=+DQ$S1f zB%hQKXH9&JoZt&J;XsjpL$G8+FJ>oh0JU+8tv-qApCh7AmmtFXT*{s%ntLo7^2ho= z3~h&+k*KFnUWIXbZU!0M|2w`AILQmN+P_q{Zjp0&qkSlAtQU^a*%652L zf=|1)Z$t}WjF`kkme;mM|E0+^RMd6MpX46~ZL#uYz9KDBCNQ78RS+>v>557(b({=- zdHvB8`V23PR_}HTxkl9#YUI_&q+d@Bpd+~3W+xs!5DHjEx_+o<_IovpFy;)RP&p(O zaq#4f-ZDX0ppg0jG|EH*3q)m1X3Av*G`OQ10oe^}SaKG#mV)Jh9{TFvc8+%DEh%pV z&jQJG@;@;#wiSXeE5_pSv^5(S%5$hYxZ3mG8s0XFRUc;0P@C%oa;#cb3wCE4rZ_s; zwi+f~_-3^RD;r6o8&h6yEF9KV$$j+TsEugMUNP7q(3n%dYl>DEfyBHlWnSVKoiv}! z?X9uhrc-@MPx`r8*h~E_2XP6329}WWXL9dsB}&@))BVyX=2H)C;?(b3b~4*LF`b9!lhqc%DDz ztTXDYh0&}ey@*R^-rA_Z!c5n*(QYoRkbHGar(3N=E=bPZtIhMJBi}cTHh1#iZn+{nCPMi}zU;k5RrAR(xsrAQv*T{etJoVcHoqPkgkv=1va=5#!G}YGvgfmq6 zLFv!e2MTxGAuA}7bbhx@Fz(dm$Au;rQS=puyZP$o7xKwSW*usaF9(D<&-h8xEKG>~ z${FlUluzuvA1@FBVTyRRYeBvzu&}7(Fv-%$FbT@-@~10;aj(>HCmFB!*X8uuMv#I< zkpY7WSf*~OHtf}Q;bs56DhYcht$jM5{4^ZbU-ohe6fY^a^NT!B%62~rOQL}_Z*AQp z^|{wb&}ZZChINAQJd`>u1Djaev!iWr36h(UFfF1dcoS%&-0&tRYHPo%iN3%QKTiG8 z4&^x>p#>#9mqm->7ZFj-a2{%pR=}Kr&er7y@P=)EDrnoRahRT${5$_cfU}_}&K?+Q zC@+JutDM^q5O;QqKgDd~J#i@1rDIcDtypRX+ARL;+RXEn(h>Q#bfB~H0N_=S9J6)( z_w?CkHM&LXwrlr#+1{trcrK=2iMTA%Gpavadi2mDw@&v@N?fWStM<#z8z9qBOIPXc zz<_0BL$1WSy-uY>HXI?sI1_X~F5&I>NPgZU^YdjXm0Vwr#WI&d8lhPW{uW#A#QM^d z>7t0=&duLbk9U@Amm5%vZ7!L<*a@kl_0fMNiL6y8X9JhJy3Wt8-cj zcc8oVvBtihca@b%Q@LXP3S`+{wQIpTKKgwV=$<`fw?Vj`%kbr5-7X^>v~Le`t!5H! z;zhqQ9HYe!=)vFV4yVlF=F^S%7V=>=^#ohPr1McLvmMVndxd^leEU}Yu1av{Z=;oJ z>nyF2vdDa!M>KI6!Cjk3K}otc>WGMuy7bK3gihW|w>1dE%^95n1dt=l_JrK4@3D!e zc?;s~x)TWT8Tl6|uF)7#?}-Z&j;WYa+NEiA8Fen{=?=@Rp)QWt%AXI-AqJ(z_>2+g zao5sAX%!ruIeKOlZ(7^prw^%+BLr`h;TQtmaHw{mQS6@r1b%jL*Vp-ohShoAkfIow?ts+UGKvjXfHjF4Ff(oZE-OKe zR9kNhy`t4aBx%S3Aarl{j0e`JStR36ivxUqpufd-HBxw9h_7*y1Sk5QDUwhEM~R2? zv_QKIUTM|jwk=YB3ku(3!c#mE{%SWDxm5j3{IvqPx~uKA;x$w1i?xt$@gE!6eqmur z)edTuqnh7q=MM+jGi-G@&&`x#R*MHlYHUvgTbm>nzJ7ASQ0Sh5zp1gx@$~1oH{4-* z@oIS2af+lwXer5Vw0u=dbnnkGn;ID?shIZCKd2j8W-d}xc&E98eP_j7E*V`IMb!fZpKH&P>$Q-kTBf&Ax zc|f=({|jR&4gW9+8#2v?&hA>(mC;RAWybl4x}WhsE;lE+X!>n(MEREB+V*udE)moF zpr>g$YFNR$-dCm@W)r&Nz0L2c=m($5n`t3ZZNnoDBfmza2s7P3P@k#8TF_V5i5+-a zkj<}DyeEl!<#k8Ob^D!QDTQpd=!0)agpf&9O$pb7mc&Byn&2CN{E79R`uqlGla|Wx z{yZsVcWqLzlJ~VlP1y}V(lsz4(CTQrZWX8<%TU%Rcws!u#yQ;LLgf!6jpZh;V|@;| zgkHDm_D%_`e{^*G!7Sn4YW*~w-mSFuUXKc2wuNgOvtOFwU7LaL)*Ss)wfFtsvCSTo zm%aP*jMkOeM2Y7xjpI-!F1Dv~nMZJ(m_Y=tK050uE-0gYATJnqK8=;ODw}JnX#d%E z_G&hq$MsOk0{TITM=Po8bI1t%KUWKPs-2wTI?-42AwJ0bXsFJKBOAzGtHmBN}4;jmVW?x z4tot--AVQI%$RPsN~ygwQ2lkt(HZW0r_3>v)1HmU>QBzg1A+xPM}g%Tqw3=?ewqy( zD@QEWUnTs=hxY{Ia1z%We{Ax@)RZ2(Xh4$>mRd$zSK0{M3RFxe3;JPV_JK9-DOohP!a|cKG&TKY{{VQieEDPH>>-ME~W^;gXt$>t8 z<9q2GTmJ1)g1Yem2-!ox`s9nxmVM(5(n^- zmm*ppj1QlR+b#$|PgeQF3n0Q=P9HLzY;Z%IPf0T)hJAB66rWr!wwL5X!!)?!Pizbm z@lFdo+XkH05)q1!((Jd74hcDvdyS3F$i_H}%f%-=1h;2>?tSiKeE06jaDMHFohlZ( z7|w|{N*61MDbgu@UVJB>Vob^Qj?-EDYH>z{RJCmUJ4X$>tNC+Qwb#izt4jxcZ{ zL^j~mwAj!?;_Ge`j@BT#k{B-fVw%>N5jKo zN;+&m|HxVYkfe`3bQ8G&NZUK6mnq`Hg>Wm}?wNXXls~R1#4(uDBZ((6#B}tfy-_3x zHLovzm>H0`R8%3gayeP!r4pv>Q+m?Sft3Bj8%c3#u|CdSa)%flYmG0mJCQ}V@ns=+ z+pVQJhVnrFfNO4{R!zOM?+++VtyhJ(7-v<7;NJVv>NBq9(dkDe+cAD$KCzB&vg?4M?8RfQGA`}yj3UHCu4SGA;5$5uIUlgWgW0Q=0!w2`( zTm**Gqw}^GYJlU_@Z+}A{fDIeRWOTajE4BMeAbmoOMU=a_tS_U-Uq8~*Q;y(4%>CR zb<>8B-i>zK?LCWPdsPd*p`p{Y&2rU+{CGppk-LJ;oEq^C6~+W=^4Z-Pljs3AM6sl8 z&ZHPuG-QFxZZ&??ka|mY>^N!YEWv44bJ#S*ixFQ{^c|+$pPd$*f|uR7l=o1Jdf2!0 zP(p~eZBG!RYcvF{)APzZJpJ52j_av@h>E# zXhMsy1YwHMABC=65jgWlOVP&GzA;6wYrjq`O+gl@+j#fIsl&T*Lsz-7NCzF_X;fA1 z`0?@f_z>Jv(x)FxQ=W5x9;++8n6up9=B#kOR9p>a|04O?&t%BL1;3)e*;o8%KVH6U zyMr$<&A)su!&KH>nPhFV<#*y90m7yWYrwX#VUa%kds6kvkjP@{$*uVp8x)rY)E5g#MH#%@~z_^ z)hFy*r&;(lG`ofzxfZ7QHOv0SyS_V<>oK&=&sj7g%;|4i>c4`gTjUyb_br`lY%#6g zRx)=n&8*(+(VzAwuT-7HN16SfeTf~(EH$%Z|6wlLGs}H&f7WIA#Zx9arqv?O(Uzfp zOpDORlFjY!YWy->8yDZ~+rKDW8sFviqm@Cwlq*i8LPSz)`tOnI)amAzS5wbtyvJcB zc}RkLydK{%tx7A5)-mt8P-_5)b~Ik%?XI z381@;A^ZB8=3YQ!4=_y$Z5rh@Qs$M4pmV*(s*@_|U9Yu$KL@+1bcJ?)Wo?{ZGAM=P z>Z=I*`{xfIcR>$Bzs7`pU_w^sehHUz4C8w?nZBd11^xv>Q9(VsihEKLP^GakkBw6x zVS$snx8o(F3-}PAnqN*{P@fFv$349Q*>)$z+TJTnGGE^Ws!=OJk_qLVlE~dSV-t5l z@mSoXw&UH0h{vO>PBoESJao`MeZkwjkaL^xeU+wSHX^xJLss>O5S#)z$Lt2F^+C1+ zZ3aLknhkr0aRujq7RRR5K5(3$<*1)hd4f)%)UJRad=yLeR*OzReKUL>FLKmC2ba?W zuc@6AOugKEQd(RRMOaQLB3G)?!<39mt~-SgR+MuhtC`9O2ix9JTgv6m_RqCQ-#}bgqA>+n;JuzGQidza58U&e6Yt^{9$7w6U z+ia$zNK9CSzrhGh9q%V5mnD3;sX^DoE9IgW(58#$iLsZ%4>@jg6(zYCk7mz6oP0pu ziW#vgX?T08$`m~eA_Jv7C77;B`i#3>FgQ^L$2xm#wtYOx{b#Z`oGgbH9uvKq>%MCc z03H0m9v|W4zESb&EtTJbAKl|9ZV0c8d>R+ Date: Thu, 23 May 2019 13:41:10 -0400 Subject: [PATCH 40/49] StringBuffer --> StringBuilder (#1436) --- .../src/main/java/com/example/appengine/UrlFetchServlet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 5e9bf252ef269871424be3270239d6d2a399181c Mon Sep 17 00:00:00 2001 From: munkhuushmgl <45373284+munkhuushmgl@users.noreply.github.com> Date: Thu, 23 May 2019 14:52:01 -0700 Subject: [PATCH 41/49] fixed region tags and refactored some methods (#1437) * fixed region tags and refactored some methods * added missing iot tags --- .../iot/examples/DeviceRegistryExample.java | 98 +++++++------------ .../DeviceRegistryExampleOptions.java | 15 +++ .../cloud/iot/examples/MqttExample.java | 34 ++++++- .../example/cloud/iot/examples/ManagerIT.java | 2 +- 4 files changed, 82 insertions(+), 67 deletions(-) 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 From 9bbadae1c37d5b71187a64b351f10fc8bfe19cd2 Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 24 May 2019 08:25:25 -0700 Subject: [PATCH 42/49] Java 8 app migrated to Java 11 (#1435) * [WIP] Java 8 app migrated to Java 11 * Change to servlet * update comment * Add region tags and ReadMe * Update region tags and ReadMe of jetty main * fix styling * Fix ReadMe link * Add App Engine staging * Respond to PR comments * Update dependencies * fix dep --- appengine-java11/README.md | 28 ++- .../appengine-simple-jetty-main/README.md | 77 +++++++- .../appengine-simple-jetty-main/pom.xml | 33 +++- appengine-java11/cloudsql/pom.xml | 5 +- appengine-java11/custom-entrypoint/README.md | 2 +- appengine-java11/gaeinfo/pom.xml | 5 +- .../guestbook-cloud-firestore/pom.xml | 5 +- appengine-java11/helloworld-servlet/README.md | 99 ++++++++++ appengine-java11/helloworld-servlet/pom.xml | 103 ++++++++++ .../src/main/appengine/app.yaml | 18 ++ .../com/example/appengine/HelloAppEngine.java | 34 ++++ appengine-java11/http-server/README.md | 2 +- appengine-java11/kotlin-ktor/README.md | 2 +- .../micronaut-helloworld/README.md | 2 +- appengine-java11/oauth2/README.md | 2 +- appengine-java11/oauth2/pom.xml | 179 +++++++++--------- appengine-java11/quarkus-helloworld/README.md | 2 +- appengine-java11/spanner/pom.xml | 5 +- .../sparkjava-helloworld/README.md | 2 +- .../springboot-helloworld/README.md | 2 +- appengine-java11/vertx-helloworld/README.md | 2 +- 21 files changed, 491 insertions(+), 118 deletions(-) create mode 100644 appengine-java11/helloworld-servlet/README.md create mode 100644 appengine-java11/helloworld-servlet/pom.xml create mode 100644 appengine-java11/helloworld-servlet/src/main/appengine/app.yaml create mode 100644 appengine-java11/helloworld-servlet/src/main/java/com/example/appengine/HelloAppEngine.java diff --git a/appengine-java11/README.md b/appengine-java11/README.md index a84d7c24171..6800bb9e53c 100644 --- a/appengine-java11/README.md +++ b/appengine-java11/README.md @@ -6,7 +6,7 @@ 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/java/ +[ae-docs]: https://cloud.google.com/appengine/docs/standard/java11/ ## Prerequisites @@ -46,11 +46,31 @@ To switch to an Open JDK 11 in a Cloud shell session, you can use: export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 ``` -### appengine-simple-jetty-main +## Java 11 runtime -[appengine-simple-jetty-main](appengine-simple-jetty-main) is a shared artifact +### 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 `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 index 1b01e9e1e66..fc803984743 100644 --- a/appengine-java11/appengine-simple-jetty-main/README.md +++ b/appengine-java11/appengine-simple-jetty-main/README.md @@ -1,5 +1,76 @@ -# Embedded Jetty Server for running WAR files on Google App Engine Standard with Java 11 +# Embedded Jetty Server for Google App Engine Standard with Java 11 -This sample demonstrates an embedded Jetty server which instantiates an HTTP server to run a WAR file. +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). +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="11 + + org.eclipse.jetty jetty-server - 9.4.14.v20181114 + 9.4.18.v20190429 org.eclipse.jetty jetty-webapp - 9.4.14.v20181114 + 9.4.18.v20190429 jar org.eclipse.jetty jetty-util - 9.4.14.v20181114 + 9.4.18.v20190429 org.eclipse.jetty jetty-annotations - 9.4.14.v20181114 + 9.4.18.v20190429 jar org.eclipse.jetty apache-jsp - 9.4.14.v20181114 + 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/cloudsql/pom.xml b/appengine-java11/cloudsql/pom.xml index f2c650c3078..ac52c07b2fc 100644 --- a/appengine-java11/cloudsql/pom.xml +++ b/appengine-java11/cloudsql/pom.xml @@ -42,8 +42,9 @@ Dependent-jars are created and added to ${project.build.directory}/appengine-staging --> - - + + + com.example.appengine.demo simple-jetty-main diff --git a/appengine-java11/custom-entrypoint/README.md b/appengine-java11/custom-entrypoint/README.md index dab91209694..69e857258af 100644 --- a/appengine-java11/custom-entrypoint/README.md +++ b/appengine-java11/custom-entrypoint/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/gaeinfo/pom.xml b/appengine-java11/gaeinfo/pom.xml index bff2bbb14bc..d977e263758 100644 --- a/appengine-java11/gaeinfo/pom.xml +++ b/appengine-java11/gaeinfo/pom.xml @@ -39,8 +39,9 @@ Copyright 2019 Google LLC Dependent-jars are created and added to ${project.build.directory}/appengine-staging --> - - + + + com.example.appengine.demo simple-jetty-main diff --git a/appengine-java11/guestbook-cloud-firestore/pom.xml b/appengine-java11/guestbook-cloud-firestore/pom.xml index f4606c330c8..fbd3870036d 100644 --- a/appengine-java11/guestbook-cloud-firestore/pom.xml +++ b/appengine-java11/guestbook-cloud-firestore/pom.xml @@ -38,8 +38,9 @@ Dependent-jars are created and added to ${project.build.directory}/appengine-staging --> - - + + + com.example.appengine.demo simple-jetty-main 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 index c49165328be..b27ea236705 100644 --- a/appengine-java11/http-server/README.md +++ b/appengine-java11/http-server/README.md @@ -18,4 +18,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/kotlin-ktor/README.md b/appengine-java11/kotlin-ktor/README.md index 06a18770a94..8405870bcd4 100644 --- a/appengine-java11/kotlin-ktor/README.md +++ b/appengine-java11/kotlin-ktor/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/micronaut-helloworld/README.md b/appengine-java11/micronaut-helloworld/README.md index f85b50717e4..975875c96e4 100644 --- a/appengine-java11/micronaut-helloworld/README.md +++ b/appengine-java11/micronaut-helloworld/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/oauth2/README.md b/appengine-java11/oauth2/README.md index 05433527f9f..00d3c12c603 100644 --- a/appengine-java11/oauth2/README.md +++ b/appengine-java11/oauth2/README.md @@ -56,4 +56,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/oauth2/pom.xml b/appengine-java11/oauth2/pom.xml index a4592d752e6..6a1294d797c 100644 --- a/appengine-java11/oauth2/pom.xml +++ b/appengine-java11/oauth2/pom.xml @@ -28,108 +28,109 @@ Removing or replacing it should not affect the execution of the samples in anyway. --> - com.google.cloud.samples - shared-configuration - 1.0.11 + com.google.cloud.samples + shared-configuration + 1.0.11 - 11 - 11 + 11 + 11 - - - - com.example.appengine.demo - simple-jetty-main - 1 - provided - - - - - - com.google.oauth-client - google-oauth-client - 1.28.0 - provided - - - - com.google.oauth-client - google-oauth-client-servlet - 1.28.0 - provided - - - - com.google.apis - google-api-services-oauth2 - v2-rev131-1.23.0 - provided - - - - - javax.servlet - javax.servlet-api - 4.0.1 - jar - provided - - - - jstl - jstl - 1.2 - provided - + + + + + 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.2.v20170220 - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.1.1 - - - copy - prepare-package - - copy-dependencies - - - - ${project.build.directory}/appengine-staging - - - - - - + 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/quarkus-helloworld/README.md b/appengine-java11/quarkus-helloworld/README.md index 7f7908b0061..facd1c43536 100644 --- a/appengine-java11/quarkus-helloworld/README.md +++ b/appengine-java11/quarkus-helloworld/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/spanner/pom.xml b/appengine-java11/spanner/pom.xml index 93c97fb371e..9f21fb38ce0 100644 --- a/appengine-java11/spanner/pom.xml +++ b/appengine-java11/spanner/pom.xml @@ -42,8 +42,9 @@ Dependent-jars are created and added to ${project.build.directory}/appengine-staging --> - - + + + com.example.appengine.demo simple-jetty-main diff --git a/appengine-java11/sparkjava-helloworld/README.md b/appengine-java11/sparkjava-helloworld/README.md index fc25f885faf..c76adc4171e 100644 --- a/appengine-java11/sparkjava-helloworld/README.md +++ b/appengine-java11/sparkjava-helloworld/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/springboot-helloworld/README.md b/appengine-java11/springboot-helloworld/README.md index 84d1515e5a1..a466d9a13e1 100644 --- a/appengine-java11/springboot-helloworld/README.md +++ b/appengine-java11/springboot-helloworld/README.md @@ -17,4 +17,4 @@ To view your app, use command: ``` gcloud app browse ``` -Or navigate to http://.appspot.com URL. +Or navigate to `https://.appspot.com`. diff --git a/appengine-java11/vertx-helloworld/README.md b/appengine-java11/vertx-helloworld/README.md index a7571eb42ca..6f3d1dac3d4 100644 --- a/appengine-java11/vertx-helloworld/README.md +++ b/appengine-java11/vertx-helloworld/README.md @@ -14,7 +14,7 @@ See [Prerequisites](../README.md#Prerequisites). ``` ## See the application page -Navigate to http://yourprojectid.appspot.com URL. +Navigate to `https://.appspot.com`. ## The application From f27121bf4f4cee388e324038baf621ed927ac8c2 Mon Sep 17 00:00:00 2001 From: noerog <32459203+noerog@users.noreply.github.com> Date: Fri, 24 May 2019 12:52:41 -0400 Subject: [PATCH 43/49] Fix FHIR import region tag. (#1440) --- .../main/java/snippets/healthcare/fhir/FhirStoreImport.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java index 0323e2c59c8..6f79902a047 100644 --- a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreImport.java @@ -16,7 +16,7 @@ package snippets.healthcare.fhir; -// [START healthcare_import_fhir_instance] +// [START healthcare_import_fhir_resources] import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; import com.google.api.client.http.HttpHeaders; @@ -105,4 +105,4 @@ private static CloudHealthcare createClient() throws IOException { .build(); } } -// [END healthcare_import_fhir_instance] +// [END healthcare_import_fhir_resources] From 1ff443f80ad383b6cbbfcc8d6e08e6b69990b844 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Tue, 28 May 2019 12:04:37 -0700 Subject: [PATCH 44/49] Cloud Spanner: Fix samples that transfer money between albums (#1438) * Cloud Spanner: Fix samples that transfer money between albums The `writeWithTransactionUsingDml` method moved $200,000 from Album1 to Album2. However, Album1 is initialized with a budget of $100,000. As a result, you couldn't work through the getting started doc [1] from start to finish. Also, there were some unnecessary inconsistencies between `writeWithTransaction` and `writeWithTransactionUsingDml`, and neither method explicitly compared the transfer amount with the source album's existing balance. I changed the methods so they both transfer $200,000 from Album2 to Album1. I also added explicit checks against the existing balance, and I updated the tests as needed. (This is an updated version of #1432.) [1]: https://cloud.google.com/spanner/docs/getting-started/java/ * get the budget from the correct result set; update tests --- .../com/example/spanner/SpannerSample.java | 126 +++++++++--------- .../com/example/spanner/SpannerSampleIT.java | 17 +-- 2 files changed, 67 insertions(+), 76 deletions(-) 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 86f7b02adfa..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", @@ -1016,8 +1010,7 @@ public Void run(TransactionContext transaction) throws Exception { // [START spanner_query_with_parameter] static void queryWithParameter(DatabaseClient dbClient) { Statement statement = - Statement - .newBuilder( + Statement.newBuilder( "SELECT SingerId, FirstName, LastName\n" + "FROM Singers\n" + "WHERE LastName = @lastName") @@ -1047,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(); @@ -1108,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() @@ -1117,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; } @@ -1298,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"); 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 6c30a13d6c8..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(); } @@ -185,13 +182,13 @@ public void testSample() throws Exception { 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"); From 774680295daaa20a036618292e933ee3e9f2b795 Mon Sep 17 00:00:00 2001 From: Gus Class Date: Tue, 28 May 2019 12:27:43 -0700 Subject: [PATCH 45/49] Removes no-longer-used beta features section (#1441) --- .../beta-features/manager/README.md | 61 -- iot/api-client/beta-features/manager/pom.xml | 128 --- .../beta-features/manager/resources/README.md | 5 - .../manager/resources/ec_private.pem | 5 - .../manager/resources/ec_private_pkcs8 | Bin 138 -> 0 bytes .../manager/resources/ec_public.pem | 4 - .../manager/resources/rsa_cert.pem | 17 - .../manager/resources/rsa_private.pem | 28 - .../manager/resources/rsa_private_pkcs8 | Bin 1219 -> 0 bytes .../iot/examples/DeviceGatewayExample.java | 832 ------------------ .../examples/DeviceGatewayExampleOptions.java | 246 ------ .../examples/RetryHttpInitializerWrapper.java | 104 --- .../example/cloud/iot/examples/GatewayIT.java | 263 ------ 13 files changed, 1693 deletions(-) delete mode 100644 iot/api-client/beta-features/manager/README.md delete mode 100644 iot/api-client/beta-features/manager/pom.xml delete mode 100644 iot/api-client/beta-features/manager/resources/README.md delete mode 100644 iot/api-client/beta-features/manager/resources/ec_private.pem delete mode 100644 iot/api-client/beta-features/manager/resources/ec_private_pkcs8 delete mode 100644 iot/api-client/beta-features/manager/resources/ec_public.pem delete mode 100644 iot/api-client/beta-features/manager/resources/rsa_cert.pem delete mode 100644 iot/api-client/beta-features/manager/resources/rsa_private.pem delete mode 100644 iot/api-client/beta-features/manager/resources/rsa_private_pkcs8 delete mode 100644 iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExample.java delete mode 100644 iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/DeviceGatewayExampleOptions.java delete mode 100644 iot/api-client/beta-features/manager/src/main/java/com/example/cloud/iot/examples/RetryHttpInitializerWrapper.java delete mode 100644 iot/api-client/beta-features/manager/src/test/java/com/example/cloud/iot/examples/GatewayIT.java 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 ef267dd2aafee19ef2fd2d8a325262cd386a73cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 138 zcmV;50CoQ`frkPC05B5<2P%e0&OHJF1_&yKNX|V20S5$aFlzz<0R$kgPXfvpx()U# zGYN^PeKzd9$ks`Akl1{Ol(%{%u@-%yL<2$q1WW5Be*p-o-h`t6b&Vzc_Of?U=sW=d@Op$1dVFY9=|$f6k4plo~XD=DeW4OFM)qFfB*mh 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 92b8cdf4ab4981e24ec281ff9bdaf1155c923d44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0OYUcR#I&v z{m|U@yfcwzrSh7*h(=pt_J`L7ud=%IM#-Yk0d~;Rpz+y3F_&;dcED!RN>;BkZXCUC zwdsPnvBX@dsEn>E%@bf^uOamlI|>I8%8s zP4fLfTQ8?cy2q$xnD4xvoL%ocPCZ5Aqa_RpnA8CUka`8OH%3-2(ckl6l)=lc281p; zQPip~9n^r^Z(M`^rl*q)T2;AKSNn~x5Stxr&>_*8hO!;sf8pyJqFTB+e~-w=UX2Z{ zMkMx1TtLvmZmo?i7s6`f8270Qd5dv_x$~vF9*iI|r7X*@I!(e%n*sv?009Dm0RaHd z)^)bJPU^`43-L;JYmF%Y=2W&_i!9Ui{T$ql$&b9w0HmJK2UUh-hZxf%St?gR;j#Hq z^92CxDb@ChbrejhJ{u+)m(t^L(z5K8rX&wA-SxFh2Aff(2}X5NL4Phq`3&!YSbJ&^ zeRe25?`jR^z*FCrmgprHtW;dP^AAmp5K4yh=>7<@|3CJ1 zoQ}+X+eb{(7(~cLdo;q4{udPa$p$jPb5k($u)Een4~4jN`L2KV1EN@np#f;~Fa1(ZK8qdi-}dR&nLfq?+~ z;E;CXuxl?3xLDlp(Vqot&^l^yxSG2?R%q5joPmmoSGBE{t>u}Xf4sO%47`fNq|7Hv zHfxOxdYmY7FJly9&SIK={@*kbLTb8eAa5ol#D@JT8rkVKKK@$@x&emFcU0660qAQc zSz0^vL)y@$scKQouJAJLh!k~m3&ZyUfq?+%ZYh`icnvc=1bQ#+wd1#ZvFw2O^}_o+ zEPzC{m7^#{%le5^dd6~Jd0@}9z*^5dKQarUC6g2?K%#y@3o}_daC#-eW8<2Z@@Z`c zLbjw(Nmsf7`m&apSTZk=%=V2nFoDM)@be-WZEjJ+&1tEpLxsH!`FPS|;5J;xC<}c8 zfq?+NvnWlASRdZ8L71*KIDBxcPc2(G9Ivtg-?3spZlyVqfWg7q>TrUcnNs#DMjl<| zfSEl?*}4`%lXo?|HX4fUz#6fnV=eUyx)XYC?@*WxkZLcqc53tjDKUi>n)}-3WtQnP z@om}aU=B=#ME9Ss|7ObN@Uc~`x3Jx}tNFtMfq;EW&5lYUX>&pvW5?`_4eGxHrz*>e zsD_B-ux#17h0fCXXW*Hr=*xv3NQ)1&RsXw5k?-XB{d9C@jdCO$CY>fcwhSKQd@;Po zhX1HnRbTXrJPSu5Z5T{)))`GQjXGowoSSI - * - * $ 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()); - } - } -} From 2d215ab8442e44e20b76fe6e1011cae76fad4820 Mon Sep 17 00:00:00 2001 From: noerog <32459203+noerog@users.noreply.github.com> Date: Wed, 29 May 2019 13:22:46 -0400 Subject: [PATCH 46/49] Fix region tag for FHIR store create. (#1439) --- .../main/java/snippets/healthcare/fhir/FhirStoreCreate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java index b746b009a4a..6fb00284b4b 100644 --- a/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java +++ b/healthcare/v1beta1/src/main/java/snippets/healthcare/fhir/FhirStoreCreate.java @@ -16,7 +16,7 @@ package snippets.healthcare.fhir; -// [START healthcare_delete_fhir_store] +// [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; @@ -88,4 +88,4 @@ private static CloudHealthcare createClient() throws IOException { .build(); } } -// [END healthcare_delete_fhir_store] +// [END healthcare_create_fhir_store] From 21c141accd4870b27fd890aa3a9ea1b5cf84d712 Mon Sep 17 00:00:00 2001 From: Juan Lara <1543140+jlara310@users.noreply.github.com> Date: Wed, 29 May 2019 13:05:34 -0700 Subject: [PATCH 47/49] Restrict the export url to admins and cron jobs (#1442) --- .../src/main/webapp/WEB-INF/web.xml | 9 +++++++++ 1 file changed, 9 insertions(+) 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 + + From 01edb36dca40d72e64a7a26b915ed105fc3f70aa Mon Sep 17 00:00:00 2001 From: Averi Kitsch Date: Fri, 31 May 2019 13:48:36 -0700 Subject: [PATCH 48/49] Java 11 Read Me updates (#1444) * Read me updates * Add links to docs * Updated path --- appengine-java11/README.md | 18 ++++++++++++++++++ .../appengine-simple-jetty-main/README.md | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/appengine-java11/README.md b/appengine-java11/README.md index 6800bb9e53c..29b84c82b42 100644 --- a/appengine-java11/README.md +++ b/appengine-java11/README.md @@ -48,6 +48,23 @@ To switch to an Open JDK 11 in a Cloud shell session, you can use: ## 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 @@ -59,6 +76,7 @@ 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 diff --git a/appengine-java11/appengine-simple-jetty-main/README.md b/appengine-java11/appengine-simple-jetty-main/README.md index fc803984743..9c17c933775 100644 --- a/appengine-java11/appengine-simple-jetty-main/README.md +++ b/appengine-java11/appengine-simple-jetty-main/README.md @@ -70,7 +70,7 @@ the provided server is running your application as expected. - Start the server with your `WAR` file as an argument: ``` -mvn exec:java -Dexec.args=" Date: Mon, 3 Jun 2019 15:48:31 -0400 Subject: [PATCH 49/49] Writing quickstart + test for Bigtable (#1431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Setup mvn package and copy in existing samples and tests * Fix style issues and ran tests * Writing quickstart + test for Bigtable * Updating pom with current versions * Adding default values for the system propertiesĖ† * surefire instead of failsafe * setup table for testing using cbt tool, retriggering test * Removing unnecessary code from quickstart test that was causing failures * cleaning up quickstart * Changing test variables to use GOOGLE_CLOUD_PROJECT and the instance environment variable --- .kokoro/tests/run_tests.sh | 1 + bigtable/pom.xml | 11 --- .../com/m/examples/bigtable/Quickstart.java | 59 +++++++++++++ .../m/examples/bigtable/HelloWorldTest.java | 21 +++-- .../bigtable/InstanceAdminExampleTest.java | 14 ++-- .../m/examples/bigtable/QuickstartTest.java | 82 +++++++++++++++++++ .../bigtable/TableAdminExampleTest.java | 22 ++--- 7 files changed, 171 insertions(+), 39 deletions(-) create mode 100644 bigtable/src/main/java/com/m/examples/bigtable/Quickstart.java create mode 100644 bigtable/src/test/java/com/m/examples/bigtable/QuickstartTest.java diff --git a/.kokoro/tests/run_tests.sh b/.kokoro/tests/run_tests.sh index 89e660b41e7..8ef7495ac24 100755 --- a/.kokoro/tests/run_tests.sh +++ b/.kokoro/tests/run_tests.sh @@ -56,6 +56,7 @@ if [[ "$SCRIPT_DEBUG" != "true" ]]; then 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" \ diff --git a/bigtable/pom.xml b/bigtable/pom.xml index b9570dffeb9..86934be3887 100644 --- a/bigtable/pom.xml +++ b/bigtable/pom.xml @@ -98,17 +98,6 @@ maven-project-info-reports-plugin 3.0.0 - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M3 - - - java-docs-samples-testing - instance - - - 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/test/java/com/m/examples/bigtable/HelloWorldTest.java b/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java index e19a1a17e66..522a99e0148 100644 --- a/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java +++ b/bigtable/src/test/java/com/m/examples/bigtable/HelloWorldTest.java @@ -40,8 +40,7 @@ /** Integration tests for {@link HelloWorld} */ public class HelloWorldTest { - private static final String PROJECT_PROPERTY_NAME = "bigtable.project"; - private static final String INSTANCE_PROPERTY_NAME = "bigtable.instance"; + 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; @@ -50,10 +49,17 @@ public class HelloWorldTest { 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 = System.getProperty(PROJECT_PROPERTY_NAME); - instanceId = System.getProperty(INSTANCE_PROPERTY_NAME); + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + instanceId = requireEnv(INSTANCE_PROPERTY_NAME); if (projectId == null || instanceId == null) { dataClient = null; adminClient = null; @@ -79,13 +85,6 @@ public static void afterClass() throws Exception { @Before public void setup() throws IOException { - if (adminClient == null || dataClient == null) { - throw new AssumptionViolatedException( - PROJECT_PROPERTY_NAME - + " or " - + INSTANCE_PROPERTY_NAME - + " property is not set, skipping integration tests."); - } tableId = generateTableId(); helloWorld = new HelloWorld(projectId, instanceId, tableId); adminClient.createTable(CreateTableRequest.of(tableId).addFamily("cf1")); diff --git a/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java b/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java index 8a92449ba74..b7bcee7d3aa 100644 --- a/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java +++ b/bigtable/src/test/java/com/m/examples/bigtable/InstanceAdminExampleTest.java @@ -42,7 +42,6 @@ /** Integration tests for {@link InstanceAdminExample} */ public class InstanceAdminExampleTest { - private static final String PROJECT_PROPERTY_NAME = "bigtable.project"; private static final String ID_PREFIX = "instanceadmin"; private static final String CLUSTER = "cluster"; private static String projectId; @@ -51,9 +50,16 @@ public class InstanceAdminExampleTest { 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 = System.getProperty(PROJECT_PROPERTY_NAME); + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); if (projectId == null) { adminClient = null; return; @@ -71,10 +77,6 @@ public static void afterClass() { @Before public void setup() throws IOException { - if (adminClient == null) { - throw new AssumptionViolatedException( - PROJECT_PROPERTY_NAME + " property is not set, skipping integration tests."); - } instanceId = generateId(); clusterId = generateId(); instanceAdmin = new InstanceAdminExample(projectId, instanceId, clusterId); 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 index d2163bf691a..51ed37cf053 100644 --- a/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java +++ b/bigtable/src/test/java/com/m/examples/bigtable/TableAdminExampleTest.java @@ -18,6 +18,7 @@ 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; @@ -45,8 +46,7 @@ /** Integration tests for {@link TableAdminExample} */ public class TableAdminExampleTest { - private static final String PROJECT_PROPERTY_NAME = "bigtable.project"; - private static final String INSTANCE_PROPERTY_NAME = "bigtable.instance"; + 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; @@ -54,10 +54,17 @@ public class TableAdminExampleTest { 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 = System.getProperty(PROJECT_PROPERTY_NAME); - instanceId = System.getProperty(INSTANCE_PROPERTY_NAME); + projectId = requireEnv("GOOGLE_CLOUD_PROJECT"); + instanceId = requireEnv(INSTANCE_PROPERTY_NAME); if (projectId == null || instanceId == null) { adminClient = null; return; @@ -78,13 +85,6 @@ public static void afterClass() { @Before public void setup() throws IOException { - if (adminClient == null) { - throw new AssumptionViolatedException( - INSTANCE_PROPERTY_NAME - + " or " - + PROJECT_PROPERTY_NAME - + " property is not set, skipping integration tests."); - } tableId = generateTableId(); tableAdmin = new TableAdminExample(projectId, instanceId, tableId); adminClient.createTable(CreateTableRequest.of(tableId).addFamily("cf"));