Creating Uber JAR with Payara Micro 5
Published on 21 Jun 2016

Payara Micro allows running web applications in a self-contained and easy way. Since the release of Payara Server 4.1.1.162, there is a simple way to generate an “Uber” JAR that bundles the contents of a WAR file and the classes and resources that compose Payara Micro!
Implementation
First, generate a web application to be run in Payara Server using traditional means (like Maven for example). Then, deploy this application with Payara Micro with the --outputUberJar option enabled to generate the resulting JAR file:
java -jar payara-micro-4.1.1.162.jar --deploy test-app.war --outputUberJar test-app.jar
You will get an output like the following:
Mar 26, 2020 9:51:55 PM fish.payara.micro.PayaraMicro packageUberJar
INFO: Building Uber Jar... test-app.jar
Mar 26, 2020 9:51:55 PM fish.payara.micro.PayaraMicro packageUberJar
INFO: Built Uber Jar test-app.jar in 183 (ms)
And finally, with this Uber jar created, you can just run the application using a simple Java command:
java -jar test-app.jar
With this, the Payara Micro instance will startup and deploy the original web application!
Now, what happens if you want to change the HTTP port this application uses (8080 by default)? Or disable the clustering capabilities? You can pass all compatible Payara Micro configuration options for the Uber jar generation, and when the application is run these options will be used to configure the server instance:
java -jar payara-micro-5.201.jar --deploy test-app.war --outputUberJar test-app.jar --port 9898 --noCluster
But what if we want to configure an application instance HTTP port and/or cluster configuration at runtime instead? Fear not, we can still pass these properties as arguments when running the application’s JAR:
java -jar test-app.jar --port 10080 --noCluster true
Also, we are not limited to bundling only one application in this Uber JAR, since we can package more applications by using the --deploy option multiple times:
java -jar payara-micro-5.201.jar --deploy test-app-1.war --deploy test-app-2.war --outputUberJar test-app.jar
And when you start the packaged applications in this JAR, the server will inform you how many applications were deployed:
[2020-03-26T09:56:53.923+0000] [] [INFO] [] [PayaraMicro] [tid: _ThreadID=1 _ThreadName=main] [timeMillis: 1585303013923] [levelValue: 800] Deployed 2 archive(s)
With this you can create self-contained environments for your applications and deploy them easily! Since the Micro edition of Payara Server is small in size, packaging and moving the resulting JAR is cost-effective and saves time.
The Maven Way
Usually, when creating self-contained applications; one of the most common scenarios is to create an Uber JAR using Maven, generally through the use of the shade plugin. How can developers leverage this feature of Payara Micro with a Maven setup? We can use the Maven support for Payara Micro and the exec plugin to generate the Uber JAR file in the package phase of the Maven lifecycle:
<plugin>
<groupId>fish.payara.maven.plugins</groupId>
<artifactId>payara-micro-maven-plugin</artifactId>
<version>1.0.6</version>
<configuration>
<payaraVersion>5.201</payaraVersion>
<deployWar>true</deployWar>
<commandLineOptions>
<option>
<key>--autoBindHttp</key>
</option>
</commandLineOptions>
<contextRoot>/</contextRoot>
</configuration>
<executions>
<execution>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
</plugin>
With this plugin declaration, we configure an execution for the java goal of the exec plugin to execute the fish.payara.micro.PayaraMicro class (this is the entry point for the Micro server) and pass the corresponding arguments of the WAR to deploy the resulting Uber JAR. Since the exec plugin has access to this class thanks to the Payara Micro Maven dependency, we don’t need to download the server and worry about setting the path of the server executable. With this, the configuration remains portable and easy to implement for continuous integration purposes.
Remember to add other options you want to pass to the Payara Micro server (HTTP port, cluster configuration, etc.) as arguments of the plugin configuration accordingly.
Dockerizing our Uber JAR
What if developers want to create a Docker container based on a Payara Micro Uber JAR? Although there are multiple options for this scenario, the easiest one is to use a Java based Docker image to acquire the Uber JAR and execute it. For example, we can structure the following Dockerfile:
FROM azul/zulu-openjdk-alpine:8
ENV APP_LOCATION ./test-app.jar
ENV APP_NAME application.jar
ADD $APP_LOCATION $APP_NAME
RUN chmod +x $APP_NAME
EXPOSE 8080
ENTRYPOINT java -jar $APP_NAME
And build a new image:
docker build -t payara-uber-jar ./
Notice that we are using the azul:zulu-openjdk-alpine:8 as a base image for our example. This is the Zulu Java 8 image based on the Alpine Linux Operating system, which is a very small sized distribution since we want this container to be as light as possible (this is the same base image we use for our official Payara Micro Docker image). We are using the Dockerfile ADD instruction to download our Uber JAR from an external source (in this case an uberjar in the same directory as th Dockerfile) and then simply setting our endpoint for this container to run our test application with the downloaded Uber JAR.
To start this container, we would simply execute the following command:
docker run -d -p 8080:8080 --name uber-jar
With this, it’s incredibly easy to set up a CI workflow:
- Generate the application JAR with Maven
- Build a new version of the Docker image
- Run the image!
Conclusion
Payara Micro introduces a new set of possibilities for application developers, and with the advent of complex concepts such as Microservices and DevOps, the ability to create a self-contained JAR that can run the server and application at the same time is something many developers urgently need.
Java developers should feel at ease, since with this approach Payara Server can be easily integrated with many continuous integration workflows.