CLOVER🍀

That was when it all began.

WildFly Bootable JARを試す

これは、なにをしたくて書いたもの?

WildFly Bootable JARというものが便利そうだったので、ちょっと試してみることにしました。

WildFly Bootable JARとは?

WildFly Bootable JARとはWildFly Bootable JAR Maven Pluginを使って作成する、実行可能JARファイル(WildFly Bootable JAR)を
作る仕組みです。

GitHub - wildfly-extras/wildfly-jar-maven-plugin: WildFly Bootable JAR

WildFly Bootable JAR is final!

単純化して言うと、WARなどのアプリケーションにWildFlyを追加して、WildFlyを含めて実行可能なJARファイルにする
仕組みのようです。

Spring Bootみたいですね。

WildFly Bootable JAR Maven Plugiinを使って作成したWildFly Bootable JARは、通常のWildFlyと同様に動作するそうです。
WildFly CLIを使って操作できることもできるとか。

制限事項は、以下だそうです。

  • シャットダウン中のサーバーの再起動は不可
  • 実行中の変更(WildFly CLIでの更新)は保持されず、サーバーが終了するとその変更も失われる
  • サーバーを管理者モードで起動することはできない

ドキュメントは、こちらです。

WildFly Bootable JAR Documentation

WildFly側のドキュメントにも、記載があります。

Bootable JAR Guide

いずれも、WildFlyのドキュメントのトップからたどれますね。

WildFly Documentation

登場したのは、WildFly 20からのようです。

A bootable JAR for WildFly 20

ところで、こう書くとQuarkusがあるのでは?とも思ったりするのですが、Quarkusは直接はWildFlyの代わりにはならないので
あくまでJakarta EEを使用したアプリケーションを実行可能JARとしたい場合は、こちらの仕組みを使うのがよいのでしょうね。

できることを、もう少し?

WildFly Bootable JAR Maven Pluginを使ってできることを、もう少し書いてみましょう。

テストでの利用に関しては、Arquillianを使うようです。

https://github.com/wildfly/wildfly-arquillian/tree/3.0.1.Final/container-bootable

各種サンプルは、こちら。

https://github.com/wildfly-extras/wildfly-jar-maven-plugin/tree/5.0.1.Final/examples

というわけで、まずは使ってみましょう。

環境

今回の環境は、こちらです。

$ java --version
openjdk 11.0.11 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 11.0.11, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-77-generic", arch: "amd64", family: "unix"

サンプルアプリケーション

まずは、動作確認するためのサンプルアプリケーションを作成します。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>wildfly-bootable-jar-example</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>jakarta.platform</groupId>
                <artifactId>jakarta.jakartaee-bom</artifactId>
                <version>8.0.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.enterprise</groupId>
            <artifactId>jakarta.enterprise.cdi-api</artifactId>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

簡単な、JAX-RS+CDIを使ったWebアプリケーションを用意しましょう。

src/main/java/org/littlewings/jakarta/wildfly/bootable/JaxrsActivator.java

package org.littlewings.jakarta.wildfly.bootable;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class JaxrsActivator extends Application {
}

src/main/java/org/littlewings/jakarta/wildfly/bootable/MessageResource.java

package org.littlewings.jakarta.wildfly.bootable;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@ApplicationScoped
@Path("message")
public class MessageResource {
    @Inject
    MessageService messageService;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello(@QueryParam("word") @DefaultValue("World") String word) {
        return messageService.message(word);
    }
}

src/main/java/org/littlewings/jakarta/wildfly/bootable/MessageService.java

package org.littlewings.jakarta.wildfly.bootable;

import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class MessageService {
    public String message(String word) {
        return String.format("Hello %s!!", word);
    }
}

パッケージングすると、WARファイルができます。

$ mvn package

$ ll -h target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war
-rw-rw-r-- 1 xxxxx xxxxx 4.9K  7月  3 19:01 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war

まあ、ふつうです。

WildFly Bootable JAR Maven Pluginを追加する

このサンプルアプリケーションに、WildFly Bootable JAR Maven Pluginを追加してパッケージングしてみましょう。

シンプルには、こんな感じですね。

Adding the bootable JAR Maven plugin to your pom file

    <build>
        <plugins>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-jar-maven-plugin</artifactId>
                <version>5.0.1.Final</version>
                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

feature-pack-locationで、使用するWildFlyのバージョンを指定します。今回は、24.0.0.Finalです。

Specifying the WildFly server version to use

                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                </configuration>

バージョンを指定しない場合は、最新のWildFlyが使われます。

こちらは、mvn packageで動作させるためのものです。

                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>

この状態でパッケージングすると

$ mvn package

WildFly Bootable JAR Maven Pluginが動作し

[INFO] --- wildfly-jar-maven-plugin:5.0.1.Final:package (default) @ wildfly-bootable-jar-example ---
[INFO] Provisioning server configuration based on the standalone-microprofile.xml default configuration
[INFO] Building server based on [[wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final inherit-packages=false inheritConfigs=false includedConfigs [model=standalone name=standalone-microprofile.xml]]] galleon feature-packs
[INFO] Found boot artifact org.wildfly.core:wildfly-jar-boot:jar:16.0.0.Final:provided in org.wildfly:wildfly-ee-galleon-pack:24.0.0.Final
7月 03, 2021 7:06:42 午後 org.wildfly.core.embedded.LoggerContext$JBossLoggingModuleLogger greeting
INFO: JBoss Modules version 1.11.0.Final
7月 03, 2021 7:06:42 午後 org.jboss.msc.service.ServiceContainerImpl <clinit>
INFO: JBoss MSC version 1.4.12.Final
7月 03, 2021 7:06:42 午後 org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.2.Final
7月 03, 2021 7:06:42 午後 org.jboss.as.server.ApplicationServerService start
INFO: WFLYSRV0049: WildFly Full 24.0.0.Final (WildFly Core 16.0.0.Final) starting
7月 03, 2021 7:06:43 午後 org.jboss.as.patching.installation.InstallationManagerService start
INFO: WFLYPAT0050: WildFly Full cumulative patch ID is: base, one-off patches include: none
7月 03, 2021 7:06:43 午後 org.jboss.as.server.suspend.SuspendController resume
INFO: WFLYSRV0212: Resuming server
7月 03, 2021 7:06:43 午後 org.jboss.as.server.BootstrapListener done
INFO: WFLYSRV0025: WildFly Full 24.0.0.Final (WildFly Core 16.0.0.Final) started in 1091ms - Started 29 of 32 services (3 services are lazy, passive or on-demand)
7月 03, 2021 7:06:43 午後 org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.16.0.Final
7月 03, 2021 7:06:45 午後 org.jboss.as.controller.AttributeDefinition validateAndSet
INFO: WFLYCTL0028: Attribute 'security-realm' in the resource at address '/subsystem=undertow/server=default-server/https-listener=https' is deprecated, and may be removed in a future version. See the attribute description in the output of the read-resource-description operation to learn more about the deprecation.
7月 03, 2021 7:06:45 午後 org.jboss.as.server.ApplicationServerService stop
INFO: WFLYSRV0050: WildFly Full 24.0.0.Final (WildFly Core 16.0.0.Final) stopped in 10ms
[INFO] Executing CLI, Server configuration
[INFO] CLI scripts execution done.

WARファイル以外に、-bootable.jarと付いたJARファイルが作成されます。125Mありますけど。

$ ll -h target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT*.*
-rw-rw-r-- 1 xxxxx xxxxx 125M  7月  3 19:07 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT-bootable.jar
-rw-rw-r-- 1 xxxxx xxxxx 4.9K  7月  3 19:06 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war

このJARファイルを実行すると

$ java -jar target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT-bootable.jar

文字通りWildFlyが起動します。

19:08:35,107 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Full 24.0.0.Final (WildFly Core 16.0.0.Final) started in 4582ms - Started 318 of 463 services (221 services are lazy, passive or on-demand

WARファイルは、ROOT.warとしてデプロイされます。

19:08:35,068 INFO  [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0010: Deployed "wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war" (runtime-name : "ROOT.war")

このため、コンテキストパスは/でアクセスできます。

$ curl localhost:8080/message
Hello World!!


$ curl localhost:8080/message?word=WildFly
Hello WildFly!!

動作確認もできましたね。

Bootable JAR実行時に使える引数は、こちら。

Bootable JAR arguments

起動は、wildfly-jar:runやwildfly-jar:startでも行うことができます。

$ mvn package wildfly-jar:run

wildfly-jar:runとwildfly-jar:startの違いは、バックグラウンドで動作するかどうかとなります。

wildfly-jar:startで起動した場合は、wildfly-jar:shutdownで停止する必要があります。

$ mvn wildfly-jar:shutdown

コンテキストパスを変更する場合は、contextRootというWildFly Bootable JAR Maven Pluginの設定で行うようです。

URL context path of deployed application

executionを設定しない場合は?

以下のexecutionの指定を入れない場合、

                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>

Bootable JARを作成するためのコマンドはこうなります。

$ mvn package wildfly-jar:package

先にpackageゴールを指定しておくことが必須となり、wildfly-jar:package単体では動作しません。

あくまで、デプロイ対象を先に作っておくことがポイントになります。Hollow JARの場合は微妙ですが。

wildfly-jar:runをこの前提で書こうとすると、けっこう長くなります…。

$ mvn package wildfly-jar:package wildfly-jar:run

設定を行う

Bootable JARとして構成されるWildFlyの設定を変更する方法はいくつかありますが、基本はパッケージング時でしょうね。

WildFly CLIのスクリプトを使って設定することになります。

Configuring the server during packaging

今回は、扱いません…。

コンポーネントをカスタマイズする

次に、利用するコンポーネントをカスタマイズしてみましょう。

Galleon configuration

Composing custom server with Galleon layers

ここで出てくるGalleonというのは、複数のコンポーネントで構成されるソフトウェアを作成、プロビジョニングするための
ツールです。

Galleon Documentation

要するに、WildFly Bootable JAR Maven Pluginでは、このGalleonを使って利用するコンポーネントを選択することになります。

デフォルトでは、standalone-microprofile.xml相当の構成でBootable JARが作成されるようです。

Specifying the set of Galleon layers to use

こちらでしょうかね?

https://github.com/wildfly/wildfly/blob/24.0.0.Final/galleon-pack/galleon-content/src/main/resources/configs/standalone/standalone-microprofile.xml/config.xml

コンポーネントの設定を行うには、2つの書き方があるようです。

とはいえ、互いに排他的な関係ではなさそうですが。

ただ、feature-packを使った場合はfeature-pack-locationを使ったWildFlyのバージョン指定はできなくなり、
これもfeature-packとして指定することになります。

<feature-packs>
    <feature-pack>
        <location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</location>
    </feature-pack>
    <feature-pack>
        <groupId>org.wildfly</groupId>
        <artifactId>wildfly-datasources-galleon-pack</artifactId>
        <version>1.0.6.Final</version>
    </feature-pack>
</feature-packs>

データソースを扱う場合などは、feature-packを使うことになります。

今回は、Galleon layerのみを使います。

Galleon layerにも2種類あり、基本なlayer(Basic layer)と、その組み合わせで表現されるFoundational layerがあります。

この2つのリストと、先ほどのstandalone-microprofile.xmlに書かれているlayersの内容を見ると、どのようなlayerが
選択されているのかがわかるでしょう。

    <layers>
        <include name="cloud-server"/>
        <include name="h2-default-datasource"/>
        <include name="microprofile-fault-tolerance"/>
        <include name="microprofile-health"/>
        <include name="microprofile-jwt"/>
        <include name="microprofile-metrics"/>
        <include name="microprofile-openapi"/>
        <include name="microprofile-opentracing"/>
        <include name="microprofile-rest-client"/>
        <include name="undertow-legacy-https"/>
        <exclude name="management-security-realm"/>
    </layers>

https://github.com/wildfly/wildfly/blob/24.0.0.Final/galleon-pack/galleon-content/src/main/resources/configs/standalone/standalone-microprofile.xml/config.xml

また、layerは除外することもできます。

Excluding Galleon layers

今回は、jaxrs-serverとmanagementを入れておきましょう。

                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                    <layers>
                        <layer>jaxrs-server</layer>
                        <layer>management</layer>
                    </layers>
                </configuration>

パッケージングすると
※今回はexecutionの設定は外しています

$ mvn package wildfly-jar:package

最初よりも、10MBほど小さくなりました。

$ ll -h target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT*.*
-rw-rw-r-- 1 xxxxx xxxxx 114M  7月  3 20:02 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT-bootable.jar
-rw-rw-r-- 1 xxxxx xxxxx 4.9K  7月  3 20:01 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war

jaxrs-serverはFoundational layerであり、もう少し削れます。

Basic layerである、jaxrsとcdiにしてみましょう。

                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                    <layers>
                        <layer>jaxrs</layer>
                        <layer>cdi</layer>
                        <layer>management</layer>
                    </layers>
                </configuration>

一気に半分くらいになりました。

$ ll -h target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT*.*
-rw-rw-r-- 1 xxxxx xxxxx  64M  7月  3 20:06 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT-bootable.jar
-rw-rw-r-- 1 xxxxx xxxxx 4.9K  7月  3 20:06 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war

こうやって、必要なコンポーネントを選んで、カスタマイズしていくことができます。

Basic layerには依存もあり、このあたりは自動的に解決してくれます。

ちなみに、management layerはリモートアクセスでの管理機能を提供するもので、WildFly Bootable JAR Maven Pluginでは
wildfly-jar:shutdownで使われるので、入れておいた方が良い気がします。

開発で使う

設定は、以下に1度戻します。

                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                    <layers>
                        <layer>jaxrs-server</layer>
                        <layer>management</layer>
                    </layers>
                </configuration>

ここからは、開発用途での使い方を書いていきましょう。

JARファイルをスリムにする

ここまで見てきた通り、Bootable JARはそれなりのサイズになります。

実環境では使えなくなるとは思いますが、WildFlyのモジュールをローカルのMavenリポジトリから使用することで、
JARファイルのサイズを小さくすることができます。

Provisioning a slim bootable JAR

plugin-optionsとして、jboss-maven-distを追加します。

                    <plugin-options>
                        <jboss-maven-dist/>
                    </plugin-options>

configurationとしては、こうなります。

                <configuration>
                    <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#24.0.0.Final</feature-pack-location>
                    <layers>
                        <layer>jaxrs-server</layer>
                        <layer>management</layer>
                    </layers>
                    <plugin-options>
                        <jboss-maven-dist/>
                    </plugin-options>
                </configuration>

これでパッケージングすると

$ mvn package wildfly-jar:package

Bootable JARファイルのサイズが、一気に数Mまで小さくなります。

$ ll -h target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT*.*
-rw-rw-r-- 1 xxxxx xxxxx 3.9M  7月  3 20:16 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT-bootable.jar
-rw-rw-r-- 1 xxxxx xxxxx 4.9K  7月  3 20:16 target/wildfly-bootable-jar-example-0.0.1-SNAPSHOT.war

パッケージングなどにかかる時間も、短くなります。

ソースコードの監視を使った開発モード

次は、WildFly Bootable JAR Maven Pluginでの、開発中に便利なモードを使っていきましょう。

まずは、ソースコードの監視を使った開発モードです。

Development mode with source watching

使い方は簡単で、以下のコマンドを実行します。

$ mvn wildfly-jar:dev-watch

すると、空のサーバー(Hollow JAR)が起動します。

[INFO] Hollow jar, No application deployment added to server.

あとは、ソースコードの変更を検知すると自動で再コンパイル&デプロイを行い、変更をサーバーに反映してくれます。

targetディレクトリが空の状態で起動しても、勝手にパッケージング&デプロイします。

$ curl localhost:8080/message
Hello World!!

起動後にソースコードを変更すると

@ApplicationScoped
public class MessageService {
    public String message(String word) {
        return String.format("Hello %s!??", word);
    }
}

変更を検出して再デプロイが行われます。

[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to /path/to/target/classes
[INFO] Exploding webapp
[INFO] Assembling webapp [wildfly-bootable-jar-example] in [/path/to/target/deployments/ROOT.war]
[INFO] Processing war project
[INFO] Webapp assembled in [5 msecs]
20:26:16,524 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 9) WFLYUT0022: Unregistered web context: '/' from server 'default-server'
20:26:16,580 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-3) WFLYSRV0028: Stopped deployment ROOT.war (runtime-name: ROOT.war) in 62ms
20:26:16,607 INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0009: Undeployed "ROOT.war" (runtime-name: "ROOT.war")
20:26:16,615 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-2) WFLYSRV0027: Starting deployment of "ROOT.war" (runtime-name: "ROOT.war")
20:26:16,699 INFO  [org.jboss.weld.deployer] (MSC service thread 1-8) WFLYWELD0003: Processing weld deployment ROOT.war
20:26:17,025 INFO  [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool -- 47) RESTEASY002225: Deploying javax.ws.rs.core.Application: class org.littlewings.jakarta.wildfly.bootable.JaxrsActivator
20:26:17,033 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 47) WFLYUT0021: Registered web context: '/' for server 'default-server'
20:26:17,049 INFO  [org.jboss.as.server] (management-handler-thread - 1) WFLYSRV0010: Deployed "ROOT.war" (runtime-name : "ROOT.war")

確認。

$ curl localhost:8080/message
Hello World!??

なかなか便利ではないでしょうか?

いくつかポイント、注意事項があります。

  • サーバーはフォアグラウンドで起動するので、停止はCtrl-cで行う
  • WAR、JAR、EARをサポート
  • src/main/java(デフォルト)およびsrc/main/webapp、src/main/resourcesの変更を検知して、再デプロイする
  • pom.xmlのWildFly Bootable JAR Maven Pluginの設定変更は、サーバーの再起動が必要
  • pom.xmlのWildFly Bootable JAR Maven Plugin以外の設定変更は、再デプロイが行われる
  • コンパイルエラーでは停止しない
  • マルチモジュールはサポートしていない
  • リソースファイルのフィルタリング(include/exclude)はサポートされておらず、すべて監視対象となる
開発モードサーバー+再パッケージング

もうひとつは、先に開発モードのサーバーを起動しておき、パッケージングすると自動で再デプロイする方法です。

Development mode with repackaging

最初に、wildfly-jar:devで開発サーバーを起動します。

$ mvn wildfly-jar:dev

こちらもHollow JARです。

[INFO] Hollow jar, No application deployment added to server.

このサーバーはバックグラウンドで起動します。

この状態で-Ddevを指定してパッケージングを行うと、target/deploymentsにファイルが配置、デプロイが行われます。

$ mvn package wildfly-jar:package -Ddev

あとは、ソースコードを変更してから同じように再パッケージングすると、自動でデプロイされます。

$ mvn package wildfly-jar:package -Ddev

wildfly-jar:dev-watchとの違いは、明示的な再パッケージングがデプロイのトリガーになることですね。

なお、開発サーバーはバックグラウンドで起動したままなので、wildfly-jar:shutdownで停止します。

$ mvn wildfly-jar:shutdown

この時に、management layerが必要になります。

まとめ

WildFly Bootable JAR Maven Pluginを試してみました。けっこう便利ではないでしょうか?

実際に動かす環境ではWildFlyサーバーにデプロイするようなケースでも、手元では開発モードでBootable JARで動かして確認して、
実際の環境ではデプロイ時はWARファイルで、という使い方も良いのかなと思います。

覚えておきましょう。