Stay organized with collectionsSave and categorize content based on your preferences.
If you are migrating to the latest supported Java version and
your app does not use
legacy bundled services, you must re-package your App Engine
Java 8 web application into an executable JAR file.
Your application must have aMainclass that starts a web server that responds
to HTTP requests on port 8080, which might be specified by thePORTenvironment
variable.
For example:
importcom.sun.net.httpserver.HttpServer;importjava.io.IOException;importjava.io.OutputStream;importjava.net.InetSocketAddress;publicclassMain{publicstaticvoidmain(String[]args)throwsIOException{// Create an instance of HttpServer bound to port defined by the// PORT environment variable when present, otherwise on 8080.intport=Integer.parseInt(System.getenv().getOrDefault("PORT","8080"));HttpServerserver=HttpServer.create(newInetSocketAddress(port),0);// Set root URI path.server.createContext("/",(vart)->{byte[]response="Hello World from Google App Engine Java 11.".getBytes();t.sendResponseHeaders(200,response.length);try(OutputStreamos=t.getResponseBody()){os.write(response);}});// Start the server.server.start();}}
WAR migration example (Java 11)
The following instructions demonstrate how to repackage an App Engine
Java 8hello-worldapplication as a JAR to run on the Java 11 runtime.
The migration uses theappengine-simple-jetty-mainartifact. This provides aMainclass with a simple Jetty web server that loads a WAR file and packages
your app into an executable JAR file:
Clone the Embedded Jetty Server artifact to your local machine:
App Engine deploys files located in the${build.directory}/appengine-stagingdirectory. By adding themaven-dependencyplugin to your build, App Engine installs
your specified dependencies to the correct folder.
Create anentrypointelement in yourapp.yamlfile to call theappengine-simple-jetty-mainobject and pass your WAR file as an
argument. For example, see thehelloworld-servletsampleapp.yamlfile:
Start the server with your WAR file as an argument.
For example, you can start the server in thehelloworld-servletsampleby running the following command from yourjava-docs-samples/appengine-java11/appengine-simple-jetty-main/folder:
ReplacePROJECT_IDwith the ID of your Google Cloud project. If
yourpom.xmlfile alreadyspecifies your
project ID, you don't need to include the-Dapp.deploy.projectIdproperty in the
command you run.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[[["\u003cp\u003eMigrating to the latest supported Java version requires repackaging App Engine Java 8 web applications into executable JAR files if they don't utilize legacy bundled services.\u003c/p\u003e\n"],["\u003cp\u003eThe application's \u003ccode\u003eMain\u003c/code\u003e class must initialize a web server to handle HTTP requests on port 8080, potentially configured via the \u003ccode\u003ePORT\u003c/code\u003e environment variable.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eappengine-simple-jetty-main\u003c/code\u003e artifact offers a \u003ccode\u003eMain\u003c/code\u003e class with a basic Jetty server to load WAR files, facilitating the creation of an executable JAR.\u003c/p\u003e\n"],["\u003cp\u003eTo correctly install the dependencies, you must add the \u003ccode\u003emaven-dependency\u003c/code\u003e plugin in your project's \u003ccode\u003epom.xml\u003c/code\u003e file and make sure that the files are installed to the \u003ccode\u003e${build.directory}/appengine-staging\u003c/code\u003e directory.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eapp.yaml\u003c/code\u003e file needs an \u003ccode\u003eentrypoint\u003c/code\u003e that references the \u003ccode\u003eappengine-simple-jetty-main\u003c/code\u003e object and provides your WAR file as an argument, as well as to correctly deploy, \u003ccode\u003egcloud app deploy\u003c/code\u003e or \u003ccode\u003emvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID\u003c/code\u003e can be used.\u003c/p\u003e\n"]]],[],null,["# Re-packaging a WAR file into a JAR file\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\n\nIf you are migrating to the latest supported Java version and\nyour app does not use\nlegacy bundled services, you must re-package your App Engine\nJava 8 web application into an executable JAR file.\n\nYour application must have a `Main` class that starts a web server that responds\nto HTTP requests on port 8080, which might be specified by the `PORT` environment\nvariable.\n\nFor example:\n\n\n import com.sun.net.httpserver.HttpServer;\n import java.io.IOException;\n import java.io.OutputStream;\n import java.net.InetSocketAddress;\n\n public class Main {\n\n public static void main(String[] args) throws IOException {\n // Create an instance of HttpServer bound to port defined by the \n // PORT environment variable when present, otherwise on 8080.\n int port = Integer.parseInt(System.getenv().getOrDefault(\"PORT\", \"8080\"));\n HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);\n\n // Set root URI path.\n server.createContext(\"/\", (var t) -\u003e {\n byte[] response = \"Hello World from Google App Engine Java 11.\".getBytes();\n t.sendResponseHeaders(200, response.length);\n try (OutputStream os = t.getResponseBody()) {\n os.write(response);\n }\n });\n\n // Start the server.\n server.start();\n }\n }\n\n### WAR migration example (Java 11)\n\nThe following instructions demonstrate how to repackage an App Engine\nJava 8 `hello-world` application as a JAR to run on the Java 11 runtime.\n\nThe migration uses the `appengine-simple-jetty-main` artifact. This provides a\n`Main` class with a simple Jetty web server that loads a WAR file and packages\nyour app into an executable JAR file:\n\n1. Clone the Embedded Jetty Server artifact to your local machine:\n\n git clone https://github.com/GoogleCloudPlatform/java-docs-samples\n\n Alternatively, you can [download the sample](https://github.com/GoogleCloudPlatform/java-docs-samples/archive/master.zip)\n as a zip file and extract it.\n2. Change to the directory that contains the sample code:\n\n cd java-docs-samples/appengine-java11/appengine-simple-jetty-main/\n\n3. Install the dependency locally:\n\n mvn install\n\n4. Add the following code to your project `pom.xml` file:\n\n - `appengine-simple-jetty-main` dependency: \n\n \u003cdependency\u003e\n \u003cgroupId\u003ecom.example.appengine\u003c/groupId\u003e\n \u003cartifactId\u003esimple-jetty-main\u003c/artifactId\u003e\n \u003cversion\u003e1\u003c/version\u003e\n \u003cscope\u003eprovided\u003c/scope\u003e\n \u003c/dependency\u003e\n\n - `maven-dependency` plugin: \n\n \u003cplugin\u003e\n \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n \u003cartifactId\u003emaven-dependency-plugin\u003c/artifactId\u003e\n \u003cversion\u003e3.6.1\u003c/version\u003e\n \u003cexecutions\u003e\n \u003cexecution\u003e\n \u003cid\u003ecopy\u003c/id\u003e\n \u003cphase\u003eprepare-package\u003c/phase\u003e\n \u003cgoals\u003e\n \u003cgoal\u003ecopy-dependencies\u003c/goal\u003e\n \u003c/goals\u003e\n \u003cconfiguration\u003e\n \u003coutputDirectory\u003e\n ${project.build.directory}/appengine-staging\n \u003c/outputDirectory\u003e\n \u003c/configuration\u003e\n \u003c/execution\u003e\n \u003c/executions\u003e\n \u003c/plugin\u003e\n\n App Engine deploys files located in the `${build.directory}/appengine-staging` directory. By adding the `maven-dependency` plugin to your build, App Engine installs your specified dependencies to the correct folder.\n5. Create an `entrypoint` element in your `app.yaml` file to call the\n `appengine-simple-jetty-main` object and pass your WAR file as an\n argument. For example, see the [`helloworld-servlet` sample](https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine-java11/helloworld-servlet)\n `app.yaml` file:\n\n runtime: java11\n entrypoint: 'java -cp \"*\" com.example.appengine.jetty.Main helloworld.war'\n\n6. To run your application locally:\n\n 1. Package your application:\n\n mvn clean package\n\n 2. Start the server with your WAR file as an argument.\n\n For example, you can start the server in the\n [`helloworld-servlet` sample](https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/appengine-java11/helloworld-servlet)\n by running the following command from your\n `java-docs-samples/appengine-java11/appengine-simple-jetty-main/`\n folder: \n\n mvn exec:java -Dexec.args=\"../helloworld-java8/target/helloworld.war\"\n\n 3. In your web browser, enter the following address:\n\n \u003chttp://localhost:8080\u003e\n7. To deploy your application:\n\n ### gcloud tooling\n\n ```bash\n gcloud app deploy\n ```\n\n ### Maven plugin\n\n ```\n mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID\n ```\n\n Replace \u003cvar translate=\"no\"\u003ePROJECT_ID\u003c/var\u003e with the ID of your Google Cloud project. If\n your `pom.xml` file already\n\n [specifies your\n project ID](/appengine/docs/standard/java-gen2/maven-reference#appenginedeploy)\n , you don't need to include the `-Dapp.deploy.projectId` property in the\n command you run."]]