Re-packaging a WAR file into a JAR file

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 a Main class that starts a web server which responds to HTTP requests on the port specified by the PORT environment variable, typically 8081.

For example:


public class Main {

  public static void main(String[] args) throws IOException {
    // Create an instance of HttpServer bound to port defined by the 
    // PORT environment variable when present, otherwise on 8080.
    int port = Integer.parseInt(System.getenv().getOrDefault("PORT", "8080"));
    HttpServer server = HttpServer.create(new InetSocketAddress(port), 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()) {

    // Start the server.

WAR migration example (Java 11)

The following instructions demonstrate how to repackage an App Engine Java 8 hello-world application as a JAR to run on the Java 11 runtime.

The migration uses the appengine-simple-jetty-main artifact. This provides a Main class with a simple Jetty web server that loads a WAR file and packages your app into an executable JAR file:

  1. Clone the Embedded Jetty Server artifact to your local machine:

    git clone

    Alternatively, you can download the sample as a zip file and extract it.

  2. Change to the directory that contains the sample code:

    cd java-docs-samples/appengine-java11/appengine-simple-jetty-main/
  3. Install the dependency locally:

    mvn install
  4. Add the following code to your project pom.xml file:

    • appengine-simple-jetty-main dependency:
    • maven-dependency plugin:
      App Engine deploys files located in the ${}/appengine-staging directory. By adding the maven-dependency plugin to your build, App Engine installs your specified dependencies to the correct folder.
  5. Create an entrypoint element in your app.yaml file to call the appengine-simple-jetty-main object and pass your WAR file as an argument. For example, see the helloworld-servlet sample app.yaml file:

    runtime: java11
    entrypoint: 'java -cp "*" com.example.appengine.jetty.Main helloworld.war'
  6. To run your application locally:

    1. Package your application:

      mvn clean package
    2. Start the server with your WAR file as an argument.

      For example, you can start the server in the helloworld-servlet sample by running the following command from your java-docs-samples/appengine-java11/appengine-simple-jetty-main/ folder:

      mvn exec:java -Dexec.args="../helloworld-java8/target/helloworld.war"
    3. In your web browser, enter the following address:


  7. To deploy your application:

    gcloud tooling

    gcloud app deploy

    Maven plugin

    mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

    Replace PROJECT_ID with the ID of your Google Cloud project. If your pom.xml file already specifies your project ID , you don't need to include the -Dapp.deploy.projectId property in the command you run.