Skip to the content.

Deploying Jakarta EE 9 applications with WildFly Bootable JAR

Since WildFly 21 was released, it is possible to build your application and the WildFly runtime into a single fat JAR file through the new wildfly-jar-maven-plugin . For developers, through this maven plugin, it brings the well-known Spring Boot building progress to Jakarta EE/WildFly world.

Prerequisites

Make sure you have installed the following software.

Building a Bootable JAR

Firstly add wildfly-jar-maven-plugin configuration.

<plugin>
    <groupId>org.wildfly.plugins</groupId>
    <artifactId>wildfly-jar-maven-plugin</artifactId>
    <version>${wildfly-jar-maven-plugin.version}</version>
    <configuration>
        <feature-pack-location>
            wildfly-preview@maven(org.jboss.universe:community-universe)#${wildfly.version}
        </feature-pack-location>
        <layers>
            <layer>jaxrs</layer>
        </layers>
        <plugin-options>
            <jboss-fork-embedded>true</jboss-fork-embedded>
        </plugin-options>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>package</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The feature-pack-location defines the infrastructure feature it will be used to build the application, and layers specifies which layers will be activated

More details about layers, please refer to the bootable jar documentation and read the Galleon layers chapter.

NOTE: In the feature pack, we use wildfly-preview to use the Jakarta EE 9 preview.

Run the following command to build the application.

mvn clean package -Pwildfly-bootable

Besides the generic war package built by maven war plugin, there is another jar file with -bootable.jar postfix is built by wildfly-jar-maven-plugin.

Run the following command to start application.

java -jar target\jakartaee9-starter-boilerplate-bootable.jar 

Use curl command to test the sample endpoint.

curl -v http://localhost:8080/api/greeting/JakartaEE

NOTE: In the generated bootable jar, by default it sets the application context path to root(“/”).

Deploying to OpenShift

The wildfly-jar-maven-plugin provides out-of-box cloud support. You can use it together with openshift-maven-plugin and build application into docker image from source codes and deploy to the OpenShift cluster.

There are several options to use OpenShift, check the official website for details.

The simplest way is registering RedHat hosted OpenShift cloud, it provides a free Developer sandbox plan. Once you have registered, it will provide you an interactive Web UI for developers and administrators views.

To use openshift-maven-plugin , you have to login firstly. In the OpenShift home page, click the question(?) icon button in the top right area, and click the command line tools menu item. Copy the oc login command line in the opened page. More details, please refer to this guide.

Assume you have installed OpenShift CLI, open a terminal, paste the command to login into the OpenShift cloud.

oc login ...

Next let’s configure the wildfly-jar-maven-plugin and openshift-maven-plugin.

<properties>
    <jkube.generator.from>registry.redhat.io/ubi8/openjdk-11:latest</jkube.generator.from>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>org.wildfly.plugins</groupId>
            <artifactId>wildfly-jar-maven-plugin</artifactId>
            <version>${wildfly-jar-maven-plugin.version}</version>
            <configuration>
                <feature-pack-location>
                    wildfly-preview@maven(org.jboss.universe:community-universe)#${wildfly.version}
                </feature-pack-location>
                <layers>
                    <layer>cloud-server</layer>
                </layers>
                <excluded-layers>
                    <layer>deployment-scanner</layer>
                </excluded-layers>
                <cloud/>
                <plugin-options>
                    <jboss-fork-embedded>true</jboss-fork-embedded>
                </plugin-options>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>package</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.eclipse.jkube</groupId>
            <artifactId>openshift-maven-plugin</artifactId>
            <version>${openshift-maven-plugin.version}</version>
            <executions>
                <execution>
                    <goals>
                        <goal>resource</goal>
                        <goal>build</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <enricher>
                    <config>
                        <jkube-service>
                            <type>NodePort</type>
                        </jkube-service>
                    </config>
                </enricher>
            </configuration>
        </plugin>
    </plugins>
</build>

Here we use a cloud-server layer instead of the former jaxrs, and add another openshift-maven-plugin configuration.

More details about the OpenShift maven plugin, see Eclipse JKube documentation.

Run the following command to deploy application to OpenShift cloud.

mvn clean oc:deploy -Pwildfly-openshift

After it is done, you can watch the pod nodes via the following command.

oc get pods -w

Go to the OpenShift Web UI, and click the Project in the left pane, then you can see all related resources, including Pod Nodes, Services, Routes, etc.

Click Pods, and select jakartaee9-starter-boilerplate-1-xxxxx, then switch to Terminal tab, try to use curl to check our application is working well.

curl -v http://localhost:8080/api/greeting/JakartaEE

The result is similar to the following screen.

oc-curl

Go back to Project view, and click Routes, and select jakartaee9-starter-boilerplate. In the detail page, you can find the external URL of this deployed application(or you can get it via the following command).

Try to access the sample API endpoint through the external URL.

$ oc get route jakartaee9-starter-boilerplate -o jsonpath="{.spec.host}"
jakartaee9-starter-boilerplate-hantsy-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com

$ curl -v http://jakartaee9-starter-boilerplate-hantsy-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com/api/greeting/JakartaEE

> GET /api/greeting/JakartaEE HTTP/1.1
> Host: jakartaee9-starter-boilerplate-hantsy-dev.apps.sandbox-m2.ll9k.p1.openshiftapps.com
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 66
< date: Thu, 15 Jul 2021 14:02:46 GMT
< set-cookie: 8f1aeb5fdab055810cd99f63982ad17b=1540c81cbcc1728a7c020191c74f5fa7; path=/; HttpOnly
< cache-control: private
<
{"message":"Say Hello to JakartaEE at 2021-07-15T14:02:46.571707"}

Running Arquillian Tests against Bootable JAR

As mentioned in the last post, WildFly Arqullian project includes a bootable container adapter for testing against the bootable jar.

Add the following dependency in the project pom.xml file.

<dependency>
    <groupId>org.wildfly.arquillian</groupId>
    <artifactId>wildfly-arquillian-container-bootable</artifactId>
    <version>${wildfly-arquillian.version}</version>
    <scope>test</scope>
</dependency>
// jerseys are omitted.

Add wildfly-jar-maven-plugin to build a bootable fat JAR for testing purpose.

<plugin>
    <groupId>org.wildfly.plugins</groupId>
    <artifactId>wildfly-jar-maven-plugin</artifactId>
    <version>${wildfly-jar-maven-plugin.version}</version>
    <configuration>
        <feature-pack-location>
            wildfly-preview@maven(org.jboss.universe:community-universe)#${wildfly.version}
        </feature-pack-location>
        <layers>
            <layer>jaxrs</layer>
            <layer>management</layer>
        </layers>
        <excluded-layers>
            <layer>deployment-scanner</layer>
        </excluded-layers>
        <plugin-options>
            <jboss-fork-embedded>true</jboss-fork-embedded>
        </plugin-options>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>package</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Create a new container in the arquillian.xml for this adapter.

<container qualifier="wildfly-bootable-jar" default="true">
    <configuration>
        <property name="jarFile">${bootable.jar}</property>
        <property name="allowConnectingToRunningServer">false</property>
        <property name="managementAddress">127.0.0.1</property>
        <property name="managementPort">9990</property>
        <property name="waitForPorts">9990</property>
        <property name="waitForPortsTimeoutInSeconds">8</property>
    </configuration>
</container>

Define a system wide property bootable.jar in the configuration of maven failsafe plugin .

 <plugin>
     <artifactId>maven-failsafe-plugin</artifactId>
     <version>${maven-failsafe-plugin.version}</version>
     <configuration>
         <systemPropertyVariables>
             <bootable.jar>${project.build.directory}/${project.artifactId}-bootable.jar
             </bootable.jar>
             <arquillian.launch>wildfly-bootable-jar</arquillian.launch>
             <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
         </systemPropertyVariables>
     </configuration>
</plugin>

Now run the tests using the following command.

mvn clean verify -Parq-wildfly-bootable-jar

Grab the example codes from my Github.