WildFly Bootable JAR is final!

As we introduced few months ago, we have been working on a "Fat JAR" packaging for WildFly. We are pleased to announce that the 2.0.0 Final version of the WildFly bootable JAR Maven plugin has been released.

WildFly 21, that has just been released (you can check the announcement), fully supports this new way of packaging applications.

A bootable JAR allows you to package both the server and your application deployment inside a single JAR file and execute it with a simple command such as java -jar myapp-bootable.jar.

Important
There is no need to re-design your application to have it executed inside a bootable JAR. Developing an application packaged as a bootable JAR is not different from developing an application for a traditional WildFly server installation using Maven.

WildFly installation strategies

Along side the WildFly zip installation and Galleon provisioning, the bootable JAR Maven plugin introduces a new way to install a WildFly server and package your applications. In order to help you identify the more appropriate installation strategy, the WildFly documentation introduces a new Installation Guide that helps you choose the best approach according to your application needs.

WildFly Bootable JAR

To help you start with this new packaging, we have defined a WildFly Bootable Guide. This guide summarizes the steps required to get started. For a detailed documentation of the Maven Plugin usage, you can read the Maven plugin documentation.

The example Maven projects are a good place to start practicing with the Maven plugin.

The WildFly quickstarts that cover Eclipse MicroProfile features have been evolved with the 'bootable-jar' and 'bootable-jar-openshift' Maven profiles allowing you to use the bootable JAR plugin.

Using Maven

Packaging your application inside a bootable JAR is done when building your application using Maven. This is done by adding an extra build step to your Maven application pom.xml file.

<build>
  <plugins>
    <plugin>
      <groupId>org.wildfly.plugins</groupId>
      <artifactId>wildfly-jar-maven-plugin</artifactId>
      <configuration>
        ...
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>package</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Then call mvn package to build both your deployment and the bootable JAR ( target/<app name>-bootable.jar file) that contains it.

The details on how to configure the build of a bootable JAR can be found in the Maven plugin documentation.

Composing a WildFly Server

Galleon layers

The Maven plugin depends on Galleon trimming capabilities to build a tailored server.

From the plugin configuration element, you need to provide the WildFly Galleon feature-pack and the list of Galleon layers you want to include/exclude.

The WildFly Galleon feature-pack is a maven artifact that contains everything needed to dynamically provision a server.

A WildFly Galleon layer is a name that identifies a server capability (e.g.: jaxrs, ejb, microprofile-config, jpa) or an aggregation of such capabilities. A layer captures a server capability in the form of:

  • A piece of server XML configuration (e.g.: extension, configured subsystem, interfaces) that describes the capability.

  • A set of JBoss modules that implements the capability.

When you are using a layer, it delivers these pieces of information in order for Galleon to assemble a server containing only the required configuration and JBoss modules.

WildFly Documentation contains a description of the WildFly Galleon layers.

An example of a plugin configuration needed to compose a server to run typical REST applications with support for distributed sessions:

<configuration>
  ...
  <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)</feature-pack-location> (1)
  <layers> (2)
    <layer>jaxrs-server</layer> (3)
    <layer>web-clustering</layer> (4)
  </layers>
</configuration>

(1) In this plugin configuration extract, we are retrieving the latest WildFly Galleon feature-pack installed in the org.jboss.universe:community-universe Galleon universe. In case you would like to provision a specific version of the server, you would need to specify the server version, for example wildfly@maven(org.jboss.universe:community-universe)#21.0.0.Final

(2) The included set of layers.

(3) jaxrs-server is a foundational layer which provides capabilities required to build typical REST applications as well as core WildFly capabilities like the logging subsystem and a secure remote management interface.

(4) web-clustering is a layer that provides Infinispan-based web session clustering.

Important
You are strongly advised to check the WildFly Galleon layers documentation in order to identify the Galleon layers that will fit your application needs.

Third-party Galleon layers

The plugin allows you to combine Galleon layers from multiple sources. A source of Galleon layers must be a Galleon feature-pack designed to be usable with WildFly.

For example, the project wildfly-datasources-galleon-pack defines a Galleon feature-pack that contains layers for postgresql, mysql and oracle drivers and datasources.

In order to compose a server from multiple source use the <feature-packs> configuration element. For example:

<configuration>
  ...
  <feature-packs>
    <feature-pack>
      <location>wildfly@maven(org.jboss.universe:community-universe)#21.0.0.Final</location>
    </feature-pack>
    <feature-pack>
      <groupId>org.wildfly</groupId>
      <artifactId>wildfly-datasources-galleon-pack</artifactId>
      <version>1.1.0.Final</version>
    </feature-pack>
  </feature-packs>
  <layers>
    <layer>cloud-server</layer> (1)
    <layer>postgresql-datasource</layer> (2)
  </layers>
</configuration>

(1) cloud-server comes from the WildFly Galleon feature-pack.

(2) postgresql-datasource comes from the wildfly-datasources-galleon-pack Galleon feature-pack.

The postgresql example shows how to combine Galleon layers from multiple sources.

Developer Experience

A strong focus has been put on "Developer Experience", in particular when it comes to development efficiency and development for cloud.

Cloud support

Adapting the server configuration to OpenShift

To properly operate in an OpenShift context, a server such as WildFly requires configuration tuning in order to adapt to the cloud execution context (e.g.:socket binding, HA cluster protocol, logging, health checks). This tuning is automatically applied when you are using the plugin to build applications for OpenShift.

When building an application to be deployed on OpenShift you need to add the <cloud> configuration element.

  <configuration>
    ...
    <cloud/>
  </configuration>

The web-clustering example shows how to build a cluster of bootable JARs running on OpenShift.

The details on how to configure a bootable JAR for cloud execution can be found in the Configuring the server for cloud execution chapter of the Maven plugin documentation.

Zero configuration with the Eclipse JKube plugin

The JKube plugin automates build and deployment of your application for OpenShift or Kubernetes. By combining the WildFly bootable JAR and JKube plugins you can achieve "zero configuration" for application deployment. No Openshift resource creation, no docker image creation, just let the plugin runs!

<build>
  <plugins>
    <plugin>
      <groupId>org.wildfly.plugins</groupId>
      <artifactId>wildfly-jar-maven-plugin</artifactId>
      <configuration>
        <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#21.0.0.Final</feature-pack-location>
        <layers>
          <layer>cloud-server</layer>
        </layers>
        <cloud/>
      </configuration>
      <executions>
        <execution>
          <goals>
           <goal>package</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <groupId>org.eclipse.jkube</groupId>
      <artifactId>openshift-maven-plugin</artifactId>
      <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>

Then call mvn oc:deploy to build your deployment, create a bootable JAR and deploy it onto openshift.

Important
Make sure you are logged in to your OpenShift Cluster prior to calling oc:deploy.

The jkube example shows how to use the WildFly bootable JAR and JKube Maven plugin.

The JKube plugin documentation contains information on how you can customize liveness and readiness probes.

Dev mode

In order to speed-up the development of your application, the Maven plugin offers the wildfly-jar:dev goal that builds and starts the bootable JAR only once. When you re-package your application, it will get automatically re-deployed in the running server.

The details on how to use the dev goal can be found in the Development mode chapter of the Maven plugin documentation.

Server configuration

In case the default configuration that Galleon layers bring is not complete, the plugin allows you to fine tune the packaged server.

WildFly CLI scripts

Although Galleon layers contains commonly used server configuration elements, it can be required to fine tune the server. The WildFly CLI tooling has been integrated into the Maven plugin in order to apply management operations during build. That is done by defining one or more CLI script files containing the list of management operations you want to see executed during packaging. For example:

A CLI script to add the org.foo.demo logging logger, set its level and configure the console handler to print log messages of all levels:

/subsystem=logging/logger=org.foo.demo:add
/subsystem=logging/logger=org.foo.demo:write-attribute(name=level,value=ALL)
/subsystem=logging/console-handler=CONSOLE:write-attribute(name=level,value=ALL)

The plugin configuration extract used to set the CLI script to be executed:

<configuration>
  ...
  <cli-sessions>
    <cli-session>
      <script-files>
        <script>scripts/logging.cli</script>
      </script-files>
    </cli-session>
  </cli-sessions>

The logging example shows how to configure the logging subsystem using WildFly CLI.

Packaging extra content

Sometime you need to package content along with the server (e.g.: a keystore, some properties files). The server packaged inside a bootable JAR uses the exact same file system layout as a WildFly installation. The plugin allows you to specify a directory (layout similar to a WildFly home directory) that gets copied into the packaged server.

For example, to copy mykeystore.jks to the standalone/configuration directory, create the directory <project base dir>/my-custom-content that contains standalone/configuration/mykeystore.jks and reference it from the plugin configuration. For example:

<configuration>
  ...
  <extra-server-content-dirs>
    <extra-content>my-custom-content</extra-content>
  </extra-server-content-dirs>
</configuration>

The https example shows how to package extra content.

Testing with Arquillian

WildFly Arquillian 3.0 contains support for a WildFly bootable JAR allowing you to test deployments with Arquillian.

The org.wildfly.arquillian:wildfly-arquillian-container-bootable adapter for arquillian supports:

  • Execution of tests that run as a client against a running bootable JAR.

  • Execution of tests that run inside a running bootable JAR but with some limitations. The bootable JAR to test must be a Hollow JAR (a JAR that doesn’t contain any deployment). There is no support yet to repackage an existing deployment to contain the classes of the deployment created by the test.

The arquillian examples show how to use WildFly arquilian to test deployments running inside a bootable JAR.

To conclude

We hope that you are seeing an interest in this new WildFly application packaging; keep us posted with your feedback and new requirements (that you can log as new project issues).

Thank-you.

JF Denise