Embed a WebSphere Liberty profile in an executable JAR with Maven
Perhaps is has something to do with my long history of working with the WebSphere Application Server, but I’ve found myself favoring the WebSphere Liberty profile whenever the opportunity arises to embed a servlet runtime within an executable JAR file. In this WebSphere Liberty profile tutorial, I’d like to demonstrate just how easy it is to take an existing Java web app, deploy it to the WebSphere Liberty server and package the entire thing up in a runnable JAR file.
The web app to deploy to WebSphere Liberty
The first step in this process is to actually have a Java web app to deploy. I used Eclipse’s New Maven Project wizard to create a simple webapp with nothing more than a humble JSP that spits out the date. This isn’t a complicated RESTful web service, or a Spring Boot MVC application, but since this WebSphere Liberty tutorial is focused on creating an embedded JAR, and not the fundamentals of web application development, it doesn’t have to be.
<html> <body> <h2>Hello WebSphere Liberty Profile World!</h2> If this prints the date, the executable JAR file is working! <%= new java.util.Date() %> </body> </html>
The generated application also contained a web.xml file, which isn’t needed in modern Java web apps, but Maven generated a simple one for backwards compatibility.
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Embedded WebSphere Liberty Example</display-name> </web-app>
The Open Liberty Maven plugin
With the JSP and deployment descriptor created, the last thing to tackle in the process of embedding WebSphere Liberty inside of an executable JAR is the POM file. The Maven POM has three significant parts to it that are noteworthy:
- The preamble generated by Eclipse
- Configuration of the maven-war-plugin
- Configuration of the liberty-maven-plugin
The Maven preamble
The Eclipse generated part of the Maven POM file specifies that the application will be packaged as a deployable war. This part of the POM also indicates that the artifactId is openliberty and the version is example, which means the web application archive that gets generated will be named openliberty-example.war. The POM file as it was originally generated by the Eclipse Maven tooling is as follows:
<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 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.mcnz.liberty.tutorial</groupId> <artifactId>openliberty</artifactId> <packaging>war</packaging> <version>example</version> <name>embedded WebSphere liberty example</name> </project>
The Maven WAR plugin
The Maven war plugin is needed package the application.
Historically, WAR files have required a web.xml file, but that necessity expired with the release of the Servlet 3.0 API. However, the Apache Maven WAR plugin barks if the web.xml file does not exist unless the failOnMissingWebXml configuration attributes is stet to false. Since my application does contain a deployment descriptor, I could have left this setting out, but I figured I’d leave it in for the sake of anyone trying to deploy a modern web app on an embedded WebSphere Liberty profile and wasn’t aware of this optional setting. The configuration for the first plugin, which appears in the Maven POM file after the name tag and before the closing project tag is as follows:
<build> <plugins> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build>
Configuring the Open Liberty Maven plugin
Up to this point in the tutorial, I have been talking about WebSphere Liberty. But the plugin that will be used here is the one available for Open Liberty. Open Liberty is the open source version of the WebSphere Liberty server, which can be used without the licensing requirements surrounding the IBM’s flagship WebSphere Liberty profile offering.
The Open Liberty plugin entry, which is placed immediately after the closing tag of the maven-war-plugin, is as follows:
<plugin> <groupId>net.wasdev.wlp.maven.plugins</groupId> <artifactId>liberty-maven-plugin</artifactId> <version>2.4.2</version> <configuration> <assemblyArtifact> <groupId>io.openliberty</groupId> <artifactId>openliberty-runtime</artifactId> <version>18.0.0.2</version> <type>zip</type> </assemblyArtifact> <packageFile>target/embedded-liberty.jar</packageFile> <include>runnable</include> <looseApplication>false</looseApplication> <installAppPackages>project</installAppPackages> </configuration> <executions> <execution> <id>install-liberty</id> <phase>prepare-package</phase> <goals> <goal>install-server</goal> <goal>create-server</goal> <goal>install-feature</goal> </goals> </execution> <execution> <id>embed-liberty</id> <phase>package</phase> <goals> <goal>install-apps</goal> <goal>package-server</goal> </goals> </execution> </executions> </plugin>
There is a lot of meat to the Open Liberty Maven plugin conguration, but these are the highlights:
- Version 18.0.0.2 of the Open Liberty profile will embedded
- The executable JAR will be named embedded-liberty.jar
- Maven goals executed during the prepare-package and package phases will download the Open Liberty server, deploy the Java web app, and package the server and the deployed app in the executable JAR.
The executable Open Liberty JAR file
With the Maven POM configured, the executable Open Liberty JAR file can be created simply by running an Apache Maven package command:
C:\webphsere\embedded\openliberty>mvn clean install [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS: OPEN LIBERTY JAR EXAMPLE [INFO] Total time: 25.016 s [INFO] Finished at: 2018-07-06T14:22:21-04:00 [INFO] ------------------------------------------------------------------------
Running the embedded Open Liberty JAR file
To run the executable JAR file with Open Liberty embedded, simply move to the \target folder in which the embedded-liberty.jar file was created and issue a java -jar command.
C:\webphsere\embedded\openliberty>java -jar embedded-liberty.jar (default_host): http://localhost:9080/openliberty-example/ Application openliberty-example started in 0.458 seconds. The server installed the following: [jsp-2.3, servlet-3.1, el-3.0]. The server defaultServer is ready to run a smarter planet.
When the embedded Open Liberty server is accessed from a browser through the assigned URL, a web page opens up that displays the current date, along with a Hello World message, as per the JSP that was created as part of the application.
And that’s all there is to it. As long as your POM is configured correctly, and your application is a valid Java EE web application, deploying it to either an embedded WebSphere Liberty or an embedded Open Liberty server is a relatively painless endeavor.
The full POM, along with the code used in this embedded WebSphere Liberty profile JAR example can be found on GitHub.
Complete Maven POM for embedded Liberty server
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mcnz.liberty.tutorial</groupId>
<artifactId>openliberty</artifactId>
<packaging>war</packaging>
<version>example</version>
<name>embedded WebSphere liberty</name>
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>net.wasdev.wlp.maven.plugins</groupId>
<artifactId>liberty-maven-plugin</artifactId>
<version>2.4.2</version>
<configuration>
<assemblyArtifact>
<groupId>io.openliberty</groupId>
<artifactId>openliberty-runtime</artifactId>
<version>18.0.0.2</version>
<type>zip</type>
</assemblyArtifact>
<packageFile>target/embedded-liberty.jar</packageFile>
<include>runnable</include>
<looseApplication>false</looseApplication>
<installAppPackages>project</installAppPackages>
</configuration>
<executions>
<execution>
<id>install-liberty</id>
<phase>prepare-package</phase>
<goals>
<goal>install-server</goal>
<goal>create-server</goal>
<goal>install-feature</goal>
</goals>
</execution>
<execution>
<id>embed-liberty</id>
<phase>package</phase>
<goals>
<goal>install-apps</goal>
<goal>package-server</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>