Re-package a WAR file into a JAR file
Stay organized with collections
Save and categorize content based on your preferences.
This document describes how to re-package a Java 8 application as a JAR file to run on a supported Java runtime. To use a supported Java runtime, you can either embed a server like Jetty or containerize your application with Docker for a custom runtime without completely rewriting your application. You can run your existing WAR applications on modern Java platforms or flexible cloud environments. Choose from the following methods that best suits your deployment strategy and infrastructure:
Prepare your Java 8 web application (WAR file)
Before you re-package your Java 8 application as a supported JAR file, you must
build a WAR file. This section provides a sample Java 8 application that builds
a WAR file. Follow the instructions to create a Java 8 hello-world application:
Create a
HelloServlet.javafile in your source directory:importjava.io.IOException; importjavax.servlet.ServletException; importjavax.servlet.annotation.WebServlet; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; @WebServlet("/hello") publicfinalclass HelloServletextendsHttpServlet{ /** * This method handles GET requests to the /hello endpoint. * * <p>Subclasses should not override this method. * * @param request the HttpServletRequest object * @param response the HttpServletResponse object * @throws ServletException if a servlet-specific error occurs * @throws IOException if an I/O error occurs */ @Override protectedvoiddoGet( finalHttpServletRequestrequest,finalHttpServletResponseresponse) throwsServletException,IOException{ response.setContentType("text/html"); response.getWriter().println("<h1>Hello, World!</h1>"); } }Create a
web.xmldeployment descriptor file to configure your web application:<?xmlversion="1.0"encoding="UTF-8"?> <web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>Create a landing page
index.jsp:<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>HelloAppEngine</title> </head> <body> <h1>WelcometoGoogleAppEngine!</h1> <p><ahref="hello">SayHello</a></p> </body> </html>Add the following code in the
pom.xmlfile to define the build for your Java 8 application:WAR packing configuration:
<groupId>com.example</groupId> <artifactId>HelloWorldApp</artifactId> <version>1.0</version> <packaging>war</packaging>maven-war-pluginplugin with themaven.compilersource and target set to version1.8:<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <java.version>8</java.version> </properties>javax.servlet-apidependency:<dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies>Maven configuration:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version><configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> </plugins> </build>
Your project directory should be similar to the following structure:
├── pom.xml └── src └── main ├── java │ └── com │ └── example │ └── HelloServlet.java └── webapp ├── WEB-INF │ └── web.xml └── index.jspRun
mvn installin your application's project directory to generate the WAR fileHelloWorldApp-1.0.warin the target directory.
Use Dockerfiles to deploy your application (recommended)
Custom runtimes are suitable for platforms supporting custom containers, such as App Engine custom runtimes. Custom runtimes provide flexibility by allowing you to configure the runtime environment. For an example walkthrough of deploying custom runtimes, see Create a custom runtime app in the App Engine flexible environment.
The following instructions describe how to containerize your Java 8 application using a Dockerfile:
- Prepare your Java 8 web application (WAR file)
- Build the container image and push it to Artifact Registry
- Deploy your application
Build the container image and push it to Artifact Registry
This section describes how to build a Docker image using Cloud Build and push it to an Artifact Registry repository. Follow these steps to create a container image of your application:
Create a
cloudbuild.yamlfile in your source directory to build the Docker image and push to Artifact Registry:steps: # Step 1: Build the Docker image -name:"gcr.io/cloud-builders/docker" args: -"build" -"-t" -"$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION" -"." # Step 2: Push the Docker image to Artifact Registry -name:"gcr.io/cloud-builders/docker" args: -"push" -"$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION" images: -"$LOCATION-docker.pkg.dev/$PROJECT/$REPOSITORY/SERVICE:VERSION"Replace:
- LOCATION with the Google Cloud region where you deploy your app.
- PROJECT with your Google Cloud project ID.
- REPOSITORY with the name of your Artifact Registry repository.
- IMAGE with your container image URL.
- TAG with your container image tag.
Create a Dockerfile with the following configuration:
# Use Maven to build the project with JDK 8 FROMmaven:3.8.6-openjdk-8ASbuild # Set working directory WORKDIR/app # Copy the application source code COPY.. # Build the application RUNmvncleanpackage # Use Jetty as the runtime FROMjetty:9.4-jdk8 # Set Jetty working directory WORKDIR/var/lib/jetty/webapps # Copy the built WAR file COPY--from=build/app/target/*.war./ROOT.war # Expose the default Jetty port EXPOSE8080 # Start Jetty correctly CMD["java","-Djetty.base=/var/lib/jetty","-jar","/usr/local/jetty/start.jar"]Download and install Docker to test your sample app, and run the Hello World container on your local machine.
Build the container image and push it to Artifact Registry:
gcloud builds submit .
Deploy your application
To deploy your App Engine application:
Configure your
app.yamlfile to use a custom runtime in the source directory:runtime:custom env:flex instance_class:F1 handlers: -url:/.* script:autoYour project directory should be similar to the following structure:
├── Dockerfile ├── README.md ├── app.yaml ├── cloudbuild.yaml ├── pom.xml └── src └── main ├── java │ └── com │ └── example │ └── HelloServlet.java └── webapp ├── WEB-INF │ └── web.xml └── index.jspDeploy your application using the
gcloud app deploycommand:gcloud app deploy --image-url=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:tagReplace:
- LOCATION with the Google Cloud region where you deploy your app.
- PROJECT with your Google Cloud project ID.
- REPOSITORY with the name of your Artifact Registry repository.
- IMAGE with your container image URL.
- TAG with your container image tag.
Use an embedded Java runtime
The following instructions demonstrate how to re-package an App Engine Java 8 application with an embedded server (Jetty) to run as a standalone JAR on a supported Java runtime:
- Create an embedded Jetty server
- Prepare your Java 8 web application (WAR file)
- Run the WAR file with embedded Jetty and deploy your application
Create an Embedded Jetty server
To bundle your application WAR file with an embedded Jetty server, follow these steps:
Create a
Mainclass to initialize and configure the Jetty server to run your WAR file. TheMainclass sets up the server port that defaults to8080. You can also modify the source code to use a port specified in thePORTenvironment variable. TheMainclass configures theWebAppContexthandler to serve your WAR file:importorg.eclipse.jetty.server.Server; importorg.eclipse.jetty.webapp.Configuration.ClassList; importorg.eclipse.jetty.webapp.WebAppContext; /** Simple Jetty Main that can execute a WAR file when passed as an argument. */ publicclass Main{ publicstaticvoidmain(String[]args)throwsException{ 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 defined by // the PORT environment variable when present, otherwise on 8080. intport=Integer.parseInt(System.getenv().getOrDefault("PORT","8080")); Serverserver=newServer(port); // 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. WebAppContextwebapp=newWebAppContext(); webapp.setContextPath("/"); webapp.setWar(args[0]); ClassListclasslist=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(); } }Create the Maven project file
pom.xmland add the following configuration:Set the
maven.compiler.sourceandmaven.compiler.targetproperties to a supported Java runtime:<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <jetty.version>9.4.57.v20241219</jetty.version> </properties>Add dependencies for Jetty:
<dependencies> <!--EmbeddedJettydependencies--> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${jetty.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-webapp</artifactId> <version>${jetty.version}</version> <type>jar</type> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-util</artifactId> <version>${jetty.version}</version> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-annotations</artifactId> <version>${jetty.version}</version> </dependency> <!--extraexplicitdependencyneededbecausethereisaJSPinthesample--> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>apache-jsp</artifactId> <version>${jetty.version}</version> </dependency> </dependencies>Configure the
maven-assembly-pluginproperty to package dependencies:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.0.0</version> <configuration> <finalName>jetty</finalName> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.appengine.jetty.Main</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
Your project directory should be similar to the following structure:
├─src │ └─main │ └─java │ └─jetty │ └─Main.java └─pom.xmlRun the
mvn installcommand in the Jetty runner project directory. This generates thejetty-jar-with-dependencies.jarin your target directory.Follow the instructions in the Prepare your Java 8 web application (WAR file) section to create a WAR file.
Run the WAR file with embedded Jetty and deploy your application
This section provides steps for packaging your application into an executable JAR file. Follow these instructions to package and deploy your application:
Place the generated Jetty runner JAR
jetty-jar-with-dependencies.jarand your application WAR fileHelloWorldApp-1.0.warin the same directory.Run the application using a supported Java runtime:
java-jarjetty-jar-with-dependencies.jarHelloWorldApp-1.0.war- In your web browser, navigate to http://localhost:8080. You should see your application's welcome page.
Create an
entrypointelement in yourapp.yamlfile to call thejetty-jar-with-dependenciesfile, and pass your WAR file as an argument. The version you specify in the WAR file must be the same version as thepom.xmlfile:runtime:java env:flex runtime_config: operating_system:ubuntu22 runtime_version:21 entrypoint:"java-jarjetty-jar-with-dependencies.jarsample.war" handlers: -url:/.* script:this field is required, but ignored manual_scaling: instances:1Deploy your application using the
gcloud app deploycommand.