diff --git a/appengine-java8/helloworld/README.md b/appengine-java8/helloworld/README.md
new file mode 100644
index 00000000000..2b9ee6cec2a
--- /dev/null
+++ b/appengine-java8/helloworld/README.md
@@ -0,0 +1,91 @@
+HelloWorld for App Engine Standard (Java 8)
+============================
+
+This sample demonstrates how to deploy an application on Google App Engine.
+
+See the [Google App Engine standard environment documentation][ae-docs] for more
+detailed instructions.
+
+[ae-docs]: https://cloud.google.com/appengine/docs/java/
+
+
+* [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
+* [Maven](https://maven.apache.org/download.cgi) (at least 3.5)
+* [Gradle](https://gradle.org/gradle-download/) (optional)
+* [Google Cloud SDK](https://cloud.google.com/sdk/) (aka gcloud)
+
+## Setup
+
+• Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/)
+
+```
+gcloud init
+```
+
+* Create an App Engine app within the current Google Cloud Project
+
+```
+gcloud app create
+```
+
+* In the `pom.xml`, update the [App Engine Maven Plugin](https://cloud.google.com/appengine/docs/standard/java/tools/maven-reference)
+with your Google Cloud Project Id:
+
+```
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+ myProjectId
+ GCLOUD_CONFIG
+
+
+```
+**Note:** `GCLOUD_CONFIG` is a special version for autogenerating an App Engine
+version. Change this field to specify a specific version name.
+
+## Maven
+### Running locally
+
+ mvn package appengine:run
+
+To use vist: http://localhost:8080/
+
+### Deploying
+
+ mvn package appengine:deploy
+
+To use vist: https://YOUR-PROJECT-ID.appspot.com
+
+## Gradle
+### Running locally
+
+ gradle appengineRun
+
+If you do not have gradle installed, you can run using `./gradlew appengineRun`.
+
+To use vist: http://localhost:8080/
+
+### Deploying
+
+ gradle appengineDeploy
+
+If you do not have gradle installed, you can deploy using `./gradlew appengineDeploy`.
+
+To use vist: https://YOUR-PROJECT-ID.appspot.com
+
+## Testing
+
+ mvn verify
+
+ or
+
+ gradle test
+
+As you add / modify the source code (`src/main/java/...`) it's very useful to add [unit testing](https://cloud.google.com/appengine/docs/java/tools/localunittesting)
+to (`src/main/test/...`). The following resources are quite useful:
+
+* [Junit4](http://junit.org/junit4/)
+* [Mockito](http://mockito.org/)
+* [Truth](http://google.github.io/truth/)
diff --git a/appengine-java8/helloworld/build.gradle b/appengine-java8/helloworld/build.gradle
new file mode 100644
index 00000000000..e18ed2be836
--- /dev/null
+++ b/appengine-java8/helloworld/build.gradle
@@ -0,0 +1,86 @@
+// 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.
+// [START gradle]
+buildscript { // Configuration for building
+ repositories {
+ jcenter() // Bintray's repository - a fast Maven Central mirror & more
+ mavenCentral()
+ }
+ dependencies {
+ classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.2.0' // If a newer version is available, use it
+ }
+}
+
+repositories { // repositories for Jar's you access in your code
+ maven {
+ url 'https://oss.sonatype.org/content/repositories/snapshots' // SNAPSHOT repository (if needed)
+ }
+ mavenCentral()
+ jcenter()
+}
+
+apply plugin: 'java' // standard Java tasks
+apply plugin: 'war' // standard Web Archive plugin
+apply plugin: 'com.google.cloud.tools.appengine' // App Engine tasks
+
+dependencies {
+ compile 'com.google.appengine:appengine-api-1.0-sdk:+' // Latest App Engine Api's
+ providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
+
+ compile 'jstl:jstl:1.2'
+
+// Add your dependencies here.
+// compile 'com.google.cloud:google-cloud:+' // Latest Cloud API's http://googlecloudplatform.github.io/google-cloud-java
+
+ testCompile 'junit:junit:4.12'
+ testCompile 'com.google.truth:truth:0.33'
+ testCompile 'org.mockito:mockito-all:1.10.19'
+
+ testCompile 'com.google.appengine:appengine-testing:+'
+ testCompile 'com.google.appengine:appengine-api-stubs:+'
+ testCompile 'com.google.appengine:appengine-tools-sdk:+'
+}
+
+// Always run unit tests
+appengineDeploy.dependsOn test
+appengineStage.dependsOn test
+
+appengine { // App Engine tasks configuration
+ deploy { // deploy configuration
+ projectId = System.getenv('GOOGLE_CLOUD_PROJECT')
+ version = '1'
+ }
+}
+
+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 )
+ }
+}
+
+group = "com.example.appenginej8" // Generated output GroupId
+version = "1.0-SNAPSHOT" // Version in generated output
+
+sourceCompatibility = 1.8 // App Engine Flexible uses Java 8
+targetCompatibility = 1.8 // App Engine Flexible uses Java 8
+// [END gradle]
diff --git a/appengine-java8/helloworld/gradle/wrapper/gradle-wrapper.properties b/appengine-java8/helloworld/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000000..883dbb1899f
--- /dev/null
+++ b/appengine-java8/helloworld/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Jun 13 16:53:48 PDT 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip
diff --git a/appengine-java8/helloworld/gradlew b/appengine-java8/helloworld/gradlew
new file mode 100755
index 00000000000..4453ccea33d
--- /dev/null
+++ b/appengine-java8/helloworld/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+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
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+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
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save ( ) {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/appengine-java8/helloworld/gradlew.bat b/appengine-java8/helloworld/gradlew.bat
new file mode 100644
index 00000000000..e95643d6a2c
--- /dev/null
+++ b/appengine-java8/helloworld/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/appengine-java8/helloworld/pom.xml b/appengine-java8/helloworld/pom.xml
new file mode 100644
index 00000000000..e527c41cdfe
--- /dev/null
+++ b/appengine-java8/helloworld/pom.xml
@@ -0,0 +1,112 @@
+
+
+
+
+ 4.0.0
+
+ war
+
+ com.example.appengine-j8
+ helloworld
+ 1.0-SNAPSHOT
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.0.17
+
+
+
+ 1.8
+ 1.8
+
+ false
+
+
+
+
+
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ 1.9.80
+
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ jar
+ provided
+
+
+
+ com.google.appengine
+ appengine-testing
+ 1.9.80
+ test
+
+
+ com.google.appengine
+ appengine-api-stubs
+ 1.9.80
+ test
+
+
+ com.google.appengine
+ appengine-tools-sdk
+ 1.9.80
+ test
+
+
+
+ com.google.truth
+ truth
+ 1.0.1
+ test
+
+
+ junit
+ junit
+ 4.13
+ test
+
+
+ org.mockito
+ mockito-core
+ 3.3.3
+ test
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+
+ myProjectId
+
+ GCLOUD_CONFIG
+
+
+
+
+
diff --git a/appengine-java8/helloworld/settings.gradle b/appengine-java8/helloworld/settings.gradle
new file mode 100644
index 00000000000..cfa69e72f24
--- /dev/null
+++ b/appengine-java8/helloworld/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * This settings file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * In a single project build this file can be empty or even removed.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user guide at https://docs.gradle.org/3.5/userguide/multi_project_builds.html
+ */
+
+/*
+// To declare projects as part of a multi-project build use the 'include' method
+include 'shared'
+include 'api'
+include 'services:webservice'
+*/
+
+rootProject.name = 'helloworld'
diff --git a/appengine-java8/helloworld/src/main/java/com/example/appengine/java8/HelloAppEngine.java b/appengine-java8/helloworld/src/main/java/com/example/appengine/java8/HelloAppEngine.java
new file mode 100644
index 00000000000..77521a0c965
--- /dev/null
+++ b/appengine-java8/helloworld/src/main/java/com/example/appengine/java8/HelloAppEngine.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.java8;
+
+import com.google.appengine.api.utils.SystemProperty;
+import java.io.IOException;
+import java.util.Properties;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
+@WebServlet(name = "HelloAppEngine", value = "/hello")
+public class HelloAppEngine extends HttpServlet {
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ Properties properties = System.getProperties();
+
+ response.setContentType("text/plain");
+ response.getWriter().println("Hello App Engine - Standard using "
+ + SystemProperty.version.get() + " Java "
+ + properties.get("java.specification.version"));
+ }
+
+ public static String getInfo() {
+ return "Version: " + System.getProperty("java.version")
+ + " OS: " + System.getProperty("os.name")
+ + " User: " + System.getProperty("user.name");
+ }
+
+}
diff --git a/appengine-java8/helloworld/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/helloworld/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..c5939d9f8ed
--- /dev/null
+++ b/appengine-java8/helloworld/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ java8
+ true
+
+
diff --git a/appengine-java8/helloworld/src/main/webapp/index.jsp b/appengine-java8/helloworld/src/main/webapp/index.jsp
new file mode 100644
index 00000000000..6dbf14a3359
--- /dev/null
+++ b/appengine-java8/helloworld/src/main/webapp/index.jsp
@@ -0,0 +1,40 @@
+
+
+<%--
+ ~ 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.
+ --%>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="com.example.appengine.java8.HelloAppEngine" %>
+
+
+
+
+
diff --git a/appengine-java8/helloworld/src/test/java/com/example/appengine/java8/HelloAppEngineTest.java b/appengine-java8/helloworld/src/test/java/com/example/appengine/java8/HelloAppEngineTest.java
new file mode 100644
index 00000000000..cc8c39c0327
--- /dev/null
+++ b/appengine-java8/helloworld/src/test/java/com/example/appengine/java8/HelloAppEngineTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.java8;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for {@link HelloAppEngine}.
+ */
+@RunWith(JUnit4.class)
+public class HelloAppEngineTest {
+ private static final String FAKE_URL = "fake.fk/hello";
+ // Set up a helper so that the ApiProxy returns a valid environment for local testing.
+ private final LocalServiceTestHelper helper = new LocalServiceTestHelper();
+
+ @Mock private HttpServletRequest mockRequest;
+ @Mock private HttpServletResponse mockResponse;
+ private StringWriter responseWriter;
+ private HelloAppEngine servletUnderTest;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ helper.setUp();
+
+ // Set up some fake HTTP requests
+ when(mockRequest.getRequestURI()).thenReturn(FAKE_URL);
+
+ // Set up a fake HTTP response.
+ responseWriter = new StringWriter();
+ when(mockResponse.getWriter()).thenReturn(new PrintWriter(responseWriter));
+
+ servletUnderTest = new HelloAppEngine();
+ }
+
+ @After public void tearDown() {
+ helper.tearDown();
+ }
+
+ @Test
+ public void doGetWritesResponse() throws Exception {
+ servletUnderTest.doGet(mockRequest, mockResponse);
+
+ // We expect our hello world response.
+ assertThat(responseWriter.toString())
+ .contains("Hello App Engine - Standard ");
+ }
+
+ @Test
+ public void helloInfoTest() {
+ String result = HelloAppEngine.getInfo();
+ assertThat(result)
+ .containsMatch("^Version:\\s+.+OS:\\s+.+User:\\s");
+ }
+}
diff --git a/appengine-java8/sparkjava-helloworld/.gitignore b/appengine-java8/sparkjava-helloworld/.gitignore
new file mode 100644
index 00000000000..2d855fa45a4
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/.gitignore
@@ -0,0 +1,4 @@
+.idea/*
+**/target/*
+*.iml
+/target/
\ No newline at end of file
diff --git a/appengine-java8/sparkjava-helloworld/README.md b/appengine-java8/sparkjava-helloworld/README.md
new file mode 100644
index 00000000000..9bb638f00c1
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/README.md
@@ -0,0 +1,72 @@
+App Engine SparkJava with Java8
+===
+
+## Sample written in SparkJava for use with App Engine Java8 Standard.
+
+See the [Google App Engine standard environment documentation][ae-docs] for more
+detailed instructions.
+
+[ae-docs]: https://cloud.google.com/appengine/docs/java/
+
+* [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
+* [Maven](https://maven.apache.org/download.cgi) (at least 3.5)
+* [Google Cloud SDK](https://cloud.google.com/sdk/) (aka gcloud command line tool)
+
+## Setup
+
+* Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/)
+
+```
+gcloud init
+```
+
+* Create an App Engine app within the current Google Cloud Project
+
+```
+gcloud app create
+```
+
+* In the `pom.xml`, update the [App Engine Maven Plugin](https://cloud.google.com/appengine/docs/standard/java/tools/maven-reference)
+with your Google Cloud Project Id:
+
+```
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+ myProjectId
+ GCLOUD_CONFIG
+
+
+```
+**Note:** `GCLOUD_CONFIG` is a special version for autogenerating an App Engine
+version. Change this field to specify a specific version name.
+
+## Maven
+### Running locally
+
+`mvn package appengine:run`
+
+To use vist: http://localhost:8080/
+
+### Deploying
+
+`mvn package appengine:deploy`
+
+To use vist: https://YOUR-PROJECT-ID.appspot.com
+
+## Testing
+
+`mvn verify`
+
+As you add / modify the source code (`src/main/java/...`) it's very useful to add [unit testing](https://cloud.google.com/appengine/docs/java/tools/localunittesting)
+to (`src/main/test/...`). The following resources are quite useful:
+
+* [Junit4](http://junit.org/junit4/)
+* [Mockito](http://mockito.org/)
+* [Truth](http://google.github.io/truth/)
+
+
+For further information, consult the
+[Java App Engine](https://developers.google.com/appengine/docs/java/overview) documentation.
diff --git a/appengine-java8/sparkjava-helloworld/pom.xml b/appengine-java8/sparkjava-helloworld/pom.xml
new file mode 100644
index 00000000000..8b358a5851c
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/pom.xml
@@ -0,0 +1,138 @@
+
+
+
+ 4.0.0
+
+ sparkjava-hello-world
+ sparkjava-hello-world-java8-war-standard
+ 1.0
+ war
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.0.17
+
+
+
+ 1.8
+ 1.8
+
+
+
+
+ com.sparkjava
+ spark-core
+ 2.9.1
+
+
+ org.eclipse.jetty
+ jetty-http
+
+
+ org.eclipse.jetty
+ jetty-io
+
+
+ org.eclipse.jetty
+ jetty-security
+
+
+ org.eclipse.jetty
+ jetty-server
+
+
+ org.eclipse.jetty
+ jetty-servlet
+
+
+ org.eclipse.jetty
+ jetty-webapp
+
+
+
+ org.eclipse.jetty.websocket
+ websocket-api
+
+
+ org.eclipse.jetty.websocket
+ websocket-client
+
+
+ org.eclipse.jetty.websocket
+ websocket-common
+
+
+ org.eclipse.jetty.websocket
+ websocket-server
+
+
+ org.eclipse.jetty.websocket
+ websocket-servlet
+
+
+
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ 1.9.80
+ jar
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ provided
+
+
+
+
+
+
+ maven-war-plugin
+ 3.2.3
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+
+ 1.8
+
+
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+
+ myProjectId
+
+ GCLOUD_CONFIG
+
+
+
+
+
+
diff --git a/appengine-java8/sparkjava-helloworld/src/main/java/HelloWorld.java b/appengine-java8/sparkjava-helloworld/src/main/java/HelloWorld.java
new file mode 100644
index 00000000000..098b42d8a36
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/src/main/java/HelloWorld.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+import static spark.Spark.get;
+
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.annotation.WebInitParam;
+import spark.servlet.SparkApplication;
+
+
+
+public class HelloWorld implements SparkApplication {
+
+ public static void main(String[] args) {
+ new HelloWorld().init();
+ }
+
+ @Override
+ public void init() {
+ get("/", (request, response)
+ -> "Hello from SparkJava running on GAE Standard Java8 runtime.");
+
+ get("/hello/:name", (request, response) -> {
+ return "SparkJava running on GAE Java8 says: Hello: " + request.params(":name");
+ });
+ }
+
+ // Use Servlet annotation to define the Spark filter without web.xml:
+ @WebFilter(
+ filterName = "SparkInitFilter", urlPatterns = {"/*"},
+ initParams = {
+ @WebInitParam(name = "applicationClass", value = "HelloWorld")
+ })
+ public static class SparkInitFilter extends spark.servlet.SparkFilter {
+ }
+}
diff --git a/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..159be9b20ab
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,25 @@
+
+
+
+ true
+ false
+ true
+ java8
+
+
+
+
diff --git a/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/logging.properties b/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/logging.properties
new file mode 100644
index 00000000000..b3b02da23df
--- /dev/null
+++ b/appengine-java8/sparkjava-helloworld/src/main/webapp/WEB-INF/logging.properties
@@ -0,0 +1,24 @@
+# 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.
+
+# A default java.util.logging configuration.
+# (All App Engine logging is through java.util.logging by default).
+#
+# To use this configuration, copy it into your application's WEB-INF
+# folder and add the following to your appengine-web.xml:
+#
+#
+#
+#
+#
+
+# Set the default logging level for all loggers to WARNING
+.level = WARNING
diff --git a/appengine-java8/springboot-helloworld/.gitignore b/appengine-java8/springboot-helloworld/.gitignore
new file mode 100644
index 00000000000..2af7cefb0a3
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/.gitignore
@@ -0,0 +1,24 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
\ No newline at end of file
diff --git a/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.jar b/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 00000000000..9cc84ea9b4d
Binary files /dev/null and b/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties b/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 00000000000..c3150437037
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip
diff --git a/appengine-java8/springboot-helloworld/README.md b/appengine-java8/springboot-helloworld/README.md
new file mode 100644
index 00000000000..4d31de6c1d8
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/README.md
@@ -0,0 +1,182 @@
+SpringBoot HelloWorld for App Engine Standard (Java 8)
+============================
+
+This sample demonstrates how to deploy a Java 8 Spring Boot application on
+Google App Engine. The Java 8 App Engine runtime expects a
+[WAR file to be uploaded](https://cloud.google.com/appengine/docs/standard/java/tools/uploadinganapp).
+
+Note: If your project's root directory includes other Maven modules, EAR packages,
+or .jar files that do not define an App Engine service, the command will fail when
+configuration files are not found.
+
+See the [Google App Engine standard environment documentation][ae-docs] for more
+detailed instructions.
+
+[ae-docs]: https://cloud.google.com/appengine/docs/java/
+
+* [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
+* [Maven](https://maven.apache.org/download.cgi) (at least 3.5)
+* [Google Cloud SDK](https://cloud.google.com/sdk/) (aka gcloud command line tool)
+
+## Setup
+
+* Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/)
+
+```
+gcloud init
+```
+
+* Create an App Engine app within the current Google Cloud Project
+
+```
+gcloud app create
+```
+
+* In the `pom.xml`, update the [App Engine Maven Plugin](https://cloud.google.com/appengine/docs/standard/java/tools/maven-reference)
+with your Google Cloud Project Id:
+
+```
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+ myProjectId
+ GCLOUD_CONFIG
+
+
+```
+**Note:** `GCLOUD_CONFIG` is a special version for autogenerating an App Engine
+version. Change this field to specify a specific version name.
+
+## Maven
+### Running locally
+
+`mvn package appengine:run`
+
+To use vist: http://localhost:8080/
+
+### Deploying
+
+`mvn package appengine:deploy`
+
+To use vist: https://YOUR-PROJECT-ID.appspot.com
+
+## Testing
+
+`mvn verify`
+
+As you add / modify the source code (`src/main/java/...`) it's very useful to add [unit testing](https://cloud.google.com/appengine/docs/java/tools/localunittesting)
+to (`src/main/test/...`). The following resources are quite useful:
+
+* [Junit4](http://junit.org/junit4/)
+* [Mockito](http://mockito.org/)
+* [Truth](http://google.github.io/truth/)
+
+
+For further information, consult the
+[Java App Engine](https://developers.google.com/appengine/docs/java/overview) documentation.
+
+## Steps to convert a Spring Boot application for App Engine Standard
+### Use the WAR packaging
+You must use WAR packaging to deploy into Google App Engine Standard.
+
+If you generate a Spring Boot project from [start.spring.io](http://start.spring.io/),
+make sure you *switch to the full version* view of the initializer site, and select *WAR*
+packaging.
+
+If you have an existing `JAR` packaging project, you can convert it into a `WAR` project by:
+1. In `pom.xml`, change `jar` to `war`
+1. Create a new `SpringBootServletInitializer` implementation:
+
+```java
+public class ServletInitializer extends SpringBootServletInitializer {
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(YourApplication.class);
+ }
+}
+```
+
+### Remove Tomcat Starter
+Google App Engine Standard deploys your `WAR` into a Jetty server. Spring Boot's starter
+includes Tomcat by default. This will introduce conflicts. Exclude Tomcat dependencies:
+```xml
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+```
+
+Do not include the Jetty dependencies. But you must include Servlet API dependency:
+```xml
+
+ javax.servlet
+ javax.servlet-api
+ 3.1.0
+ provided
+
+```
+
+### Add App Engine Standard Plugin
+In the `pom.xml`, add the App Engine Standard plugin:
+```xml
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+```
+
+This plugin is used to run local development server as well as deploying the application
+into Google App Engine.
+
+### Add App Engine Configuration
+Add a `src/main/webapp/WEB-INF/appengine-web.xml`:
+```xml
+
+ 1
+ true
+ java8
+
+```
+
+This configure is required for applications running in Google App Engine.
+
+### Exclude JUL to SLF4J Bridge
+Spring Boot's default logging bridge conflicts with Jetty's logging system.
+To be able to capture the Spring Boot startup logs, you need to exclude
+`org.slf4j:jul-to-slf4j` dependency. The easiest way to do this is to
+set the dependency scope to `provided`, so that it won't be included in
+the `WAR` file:
+
+```xml
+
+
+ org.slf4j
+ jul-to-slf4j
+ provided
+
+```
+
+### Out of memory errors
+
+With Spring Boot >= 1.5.6, you may run into out of memory errors on startup.
+Please follow these instructions to work around this issue:
+
+1. Inside src/main/resources, adding a logging.properties file with:
+```ini
+.level = INFO
+```
+2. Inside src/main/webapp/WEB-INF/appengine-web.xml, add a config that points to the new logging.properties file.
+```xml
+
+
+
+```
diff --git a/appengine-java8/springboot-helloworld/mvnw b/appengine-java8/springboot-helloworld/mvnw
new file mode 100755
index 00000000000..5bf251c0774
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/mvnw
@@ -0,0 +1,225 @@
+#!/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 Migwn, 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
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+echo $MAVEN_PROJECTBASEDIR
+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-java8/springboot-helloworld/mvnw.cmd b/appengine-java8/springboot-helloworld/mvnw.cmd
new file mode 100644
index 00000000000..019bd74d766
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/mvnw.cmd
@@ -0,0 +1,143 @@
+@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 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
+
+%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-java8/springboot-helloworld/pom.xml b/appengine-java8/springboot-helloworld/pom.xml
new file mode 100644
index 00000000000..a2a2ff642ac
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/pom.xml
@@ -0,0 +1,130 @@
+
+
+ 4.0.0
+
+ com.google.appengine.demos
+ springboot-appengine-standard
+ 0.0.1-SNAPSHOT
+ war
+
+ springboot-appengine-standard
+ Demo project for Spring Boot
+
+
+ com.google.cloud.samples
+ shared-configuration
+ 1.0.17
+
+
+
+ UTF-8
+ UTF-8
+ 2.3.0.RELEASE
+ 1.8
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring.boot.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-tomcat
+
+
+
+
+
+
+ org.slf4j
+ jul-to-slf4j
+ provided
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.1
+ provided
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring.boot.version}
+ test
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring.boot.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring.boot.version}
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.2.0
+
+
+ myProjectId
+
+ GCLOUD_CONFIG
+
+
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 2.7
+
+
+ compile
+
+ display-dependency-updates
+ display-plugin-updates
+
+
+
+
+
+ javax.servlet:javax.servlet-api
+ com.google.guava:guava
+
+
+
+
+
+ maven-war-plugin
+ 3.2.3
+
+ false
+
+
+
+
+
+
+
+
diff --git a/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/HelloworldController.java b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/HelloworldController.java
new file mode 100644
index 00000000000..f0866e71770
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/HelloworldController.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.demos.springboot;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class HelloworldController {
+ @GetMapping("/")
+ public String hello() {
+ return "Hello world - springboot-appengine-standard!";
+ }
+}
diff --git a/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/ServletInitializer.java b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/ServletInitializer.java
new file mode 100644
index 00000000000..202df907f9b
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/ServletInitializer.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.demos.springboot;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+public class ServletInitializer extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(SpringBootExampleApplication.class);
+ }
+
+}
diff --git a/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/SpringBootExampleApplication.java b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/SpringBootExampleApplication.java
new file mode 100644
index 00000000000..e0f25c84bac
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/java/com/example/appengine/demos/springboot/SpringBootExampleApplication.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.demos.springboot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringBootExampleApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootExampleApplication.class, args);
+ }
+}
diff --git a/appengine-java8/springboot-helloworld/src/main/resources/application.properties b/appengine-java8/springboot-helloworld/src/main/resources/application.properties
new file mode 100644
index 00000000000..2503fe27596
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/resources/application.properties
@@ -0,0 +1,14 @@
+ # 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.
+ #
diff --git a/appengine-java8/springboot-helloworld/src/main/resources/logging.properties b/appengine-java8/springboot-helloworld/src/main/resources/logging.properties
new file mode 100644
index 00000000000..b615738ca24
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/resources/logging.properties
@@ -0,0 +1,15 @@
+ # 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.
+ #
+.level = INFO
diff --git a/appengine-java8/springboot-helloworld/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/springboot-helloworld/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..c4a1b38d85d
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,20 @@
+
+
+
+ true
+ java8
+
+
+
+
diff --git a/appengine-java8/springboot-helloworld/src/test/java/com/example/appengine/demos/springboot/SpringBootExampleApplicationTests.java b/appengine-java8/springboot-helloworld/src/test/java/com/example/appengine/demos/springboot/SpringBootExampleApplicationTests.java
new file mode 100644
index 00000000000..e6eda8e0036
--- /dev/null
+++ b/appengine-java8/springboot-helloworld/src/test/java/com/example/appengine/demos/springboot/SpringBootExampleApplicationTests.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package com.example.appengine.demos.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 SpringBootExampleApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}