Open Liberty can package a Java web application, its server configuration and the Liberty runtime into a single executable JAR. The resulting file can be copied to another machine and started with a normal java -jar command.
This updated tutorial uses Java 26, Open Liberty 26.0.0.7, the Liberty Maven Plugin 3.12.0 and Jakarta EE 11.
The original version of this article used Open Liberty 18.0.0.2 and an older Maven plugin configuration. Modern Open Liberty uses the io.openliberty.tools plugin coordinates and can generate a minimized runnable JAR containing only the runtime features the application needs.
Open Liberty executable JAR architecture
The finished artifact contains four things:
- the Open Liberty runtime;
- the Liberty
server.xmlconfiguration; - the Java web application; and
- the Jakarta EE features required by the application.
At runtime, Open Liberty extracts the JAR to a temporary location and starts the packaged server in the foreground.
Create a Java 26 Jakarta EE web application
The application itself can be extremely small. This example uses a Jakarta Servlet 6.1 servlet rather than the old JSP scriptlet used in the original tutorial.
package com.mcnz.liberty;
import java.io.IOException;
import java.time.Instant;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@WebServlet("/")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws IOException {
response.setContentType("text/plain");
response.getWriter().println(
"Hello from Open Liberty at " + Instant.now()
);
}
}No web.xml file is required because the servlet is mapped with @WebServlet.
Configure Open Liberty for Jakarta EE 11
Create src/main/liberty/config/server.xml:
<server description="Open Liberty executable JAR">
<featureManager>
<feature>webProfile-11.0</feature>
</featureManager>
<httpEndpoint
id="defaultHttpEndpoint"
host="*"
httpPort="9080"
httpsPort="9443"/>
<webApplication
id="openliberty-example"
location="openliberty-example.war"
contextRoot="/"/>
</server>The webProfile-11.0 feature supplies the Jakarta EE 11 Web Profile, including Jakarta Servlet 6.1, Jakarta Server Pages 4.0, CDI 4.1, Persistence 3.2 and the other Web Profile APIs.
For a tiny servlet application, you could enable only the Servlet feature instead. Using the Web Profile here keeps the example ready for a broader Jakarta EE web application.
Modern Maven POM for Open Liberty
The application remains a WAR project because Liberty deploys the web application into the packaged server. The final deliverable, however, will be an executable JAR that contains both the WAR and the Liberty runtime.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mcnz.liberty</groupId>
<artifactId>openliberty-example</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.release>26</maven.compiler.release>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-web-api</artifactId>
<version>11.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>openliberty-example</finalName>
<plugins>
<plugin>
<groupId>io.openliberty.tools</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>3.12.0</version>
<configuration>
<runtimeArtifact>
<groupId>io.openliberty</groupId>
<artifactId>openliberty-runtime</artifactId>
<version>26.0.0.7</version>
<type>zip</type>
</runtimeArtifact>
<include>minify,runnable</include>
<packageName>
embedded-liberty.jar
</packageName>
</configuration>
<executions>
<execution>
<id>package-liberty</id>
<phase>package</phase>
<goals>
<goal>create</goal>
<goal>install-feature</goal>
<goal>deploy</goal>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>What changed from the old Liberty Maven plugin?
The old tutorial used these coordinates:
net.wasdev.wlp.maven.plugins:liberty-maven-plugin:2.4.2The current plugin uses:
io.openliberty.tools:liberty-maven-plugin:3.12.0The runtime configuration has also changed. Modern builds use runtimeArtifact instead of the older assemblyArtifact configuration shown in the original article.
Build the executable Open Liberty JAR
Run the Maven package phase:
mvn clean packageThe Liberty Maven plugin performs the configured lifecycle:
- Create the Liberty server.
- Install the Jakarta EE features referenced by
server.xml. - Deploy the WAR.
- Package the server as a minimized runnable JAR.
The resulting file is created under the Maven target directory:
target/embedded-liberty.jarRun the Open Liberty executable JAR
Start the application with Java 26:
java -jar target/embedded-liberty.jarWhen the server is ready, open:
http://localhost:9080/The response looks similar to this:
Hello from Open Liberty at 2026-08-14T12:00:00ZGenerate a runnable JAR without changing the POM
If the project already uses the Liberty Maven plugin but does not permanently configure runnable packaging, Open Liberty can also override the package type from the command line:
mvn liberty:package -Dinclude=runnableTo generate the smaller runtime that contains only the server features your configuration needs, use:
mvn liberty:package -Dinclude=minify,runnableThe minify option removes unused Liberty runtime features. That can reduce the size of the resulting executable JAR substantially.
Java 26 support in Open Liberty
Open Liberty added Java 26 support in the 26.0.0.4 release. Open Liberty 26.0.0.7 therefore supports running this application on Java 26.
Open Liberty also supports several LTS Java versions. For production systems, choose a Java release that matches your organization's support and upgrade policy rather than automatically selecting the newest six-month release.
Jakarta EE 11 instead of Java EE
The original 2018 application was built around Java EE-era APIs. Modern enterprise Java uses the jakarta.* namespace and Jakarta EE specifications.
Open Liberty 26 supports Jakarta EE 11. The Web Profile 11 feature used in this tutorial includes Servlet 6.1 and Server Pages 4.0, so existing JSP applications can still run after they are migrated to the modern Jakarta EE APIs where necessary.
Runnable JAR or container image?
A Liberty runnable JAR is useful when you want one portable Java artifact that includes the application and server runtime. It works well for demonstrations, development environments and deployment systems built around executable Java archives.
For cloud-native production environments, a container image is often the more common deployment unit. Open Liberty publishes container images and provides optimized container workflows as well.
The two approaches are not mutually exclusive. The important idea is that the runtime configuration belongs with the application so the same tested configuration moves through build, test and deployment environments.
Modern Open Liberty executable JAR workflow
Java 26 source
↓
Jakarta EE 11 WAR
↓
server.xml
↓
Liberty Maven Plugin 3.12.0
↓
Open Liberty 26.0.0.7
↓
minify + runnable
↓
embedded-liberty.jar
↓
java -jarThe modern Open Liberty tooling makes the overall workflow much simpler than the older manual configuration. Maven builds the WAR, installs the required Liberty features, deploys the application and packages only the runtime pieces the server actually needs.