これは、なにをしたくて書いたもの?
これまで何回かWildFly Bootable JARを使ってきましたが、そういえばWildFlyで使っていたようなシステムプロパティや起動引数の指定は
有効なのかな?とふと疑問に思ったので試してみました。
結論を言うと、同じように使えます。
WildFly Bootable JARの起動引数について
WildFly Bootable JARの起動引数については、こちらに書かれています。
以下のように、まあ見慣れたものがありますね。
-b[interface]=<value>
… Set system property jboss.bind.address.to the given value -b=<value>
… Set system property jboss.bind.address to the given value-D<name>[=<value>]
… Set a system property. The system properties are set by the server. They are not set by the bootable JAR JVM.--help
… Display help then exit …-u=<value>
… Set system property jboss.default.multicast.address to the given value.--version
… Print version and exit.
--help
も使えるんですね。
ここで、-D
を使ったシステムプロパティで指定できるのは、どのあたりなんだろうと思ったのが今回扱ったきっかけです。
お題
今回は、WildFly Bootable JARを使ってひとつのホスト内に同じアプリケーションを2つ起動させてみます。この時、なにも考えずに起動すると
ポートが重複するはずですが、-Djboss.socket.binding.port-offset
でポートをずらせるかどうか確認したいと思います。
せっかくなので、クラスタリングもしておきましょう。
環境
今回の環境は、こちら。
$ java --version openjdk 17.0.4 2022-07-19 OpenJDK Runtime Environment (build 17.0.4+8-Ubuntu-120.04) OpenJDK 64-Bit Server VM (build 17.0.4+8-Ubuntu-120.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.4, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-128-generic", arch: "amd64", family: "unix"
WildFly Bootable JARを使ったサンプルアプリケーションを作成する
それでは、アプリケーションを作成します。
まずはpom.xml
から。
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.littlewings</groupId> <artifactId>wildfly-bootable-jar-clustering</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-web-api</artifactId> <version>8.0.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.2</version> </plugin> <plugin> <groupId>org.wildfly.plugins</groupId> <artifactId>wildfly-jar-maven-plugin</artifactId> <version>8.0.1.Final</version> <configuration> <feature-pack-location>wildfly@maven(org.jboss.universe:community-universe)#26.1.2.Final</feature-pack-location> <layers> <layer>jaxrs</layer> <layer>web-clustering</layer> </layers> </configuration> <executions> <execution> <goals> <goal>package</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
レイヤーには、jaxrs
とweb-clustering
を入れました。
<layers> <layer>jaxrs</layer> <layer>web-clustering</layer> </layers>
使用するWildFlyは26.1.2.Finalとします。
HttpSession
を使ったJAX-RSリソースクラス。
src/main/java/org/littlewings/wildfly/bootable/HelloResource.java
package org.littlewings.wildfly.bootable; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; @Path("hello") public class HelloResource { @GET @Produces(MediaType.TEXT_PLAIN) public String messageAndSessionStartedTime(@Context HttpServletRequest request) { HttpSession session = request.getSession(); LocalDateTime startedTime; if (session.isNew()) { startedTime = LocalDateTime.now(); session.setAttribute("startedTime", startedTime); } return String.format( "Hello[%s]", ((LocalDateTime) session.getAttribute("startedTime")).format(DateTimeFormatter.ISO_DATE_TIME) ); } }
JAX-RSの有効化。
src/main/java/org/littlewings/wildfly/bootable/JaxrsActivator.java
package org.littlewings.wildfly.bootable; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("") public class JaxrsActivator extends Application { }
<distributable/>
が必要なので、web.xml
も作成。
src/main/webapp/WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <distributable/> </web-app>
パッケージング。
$ mvn package
起動。
$ java -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar
動作確認。
$ curl -b cookie.txt -c cookie.txt localhost:8080/hello Hello[2022-10-19T00:04:39.439503952] $ curl -b cookie.txt -c cookie.txt localhost:8080/hello Hello[2022-10-19T00:04:39.439503952] $ curl -b cookie.txt -c cookie.txt localhost:8080/hello Hello[2022-10-19T00:04:39.439503952]
ひとまず、シングルノードのアプリケーションとしてはOKです。
2つ目のアプリケーションを起動する
では、この状態で同じアプリケーションをもうひとつ起動します。
$ java -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar
当然のことながら、起動に失敗します。
00:05:55,841 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-7) MSC000001: Failed to start service org.wildfly.undertow.listener.default: org.jboss.msc.service.StartException in service org.wildfly.undertow.listener.default: アドレスは既に使用中です /127.0.0.1:8080 at org.wildfly.extension.undertow@26.1.2.Final//org.wildfly.extension.undertow.ListenerService.start(ListenerService.java:212) at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1739) at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1701) at org.jboss.msc@1.4.13.Final//org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1559) at org.jboss.threads@2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377) at java.base/java.lang.Thread.run(Thread.java:833) 00:05:56,786 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 30) MSC000001: Failed to start service org.wildfly.clustering.jgroups.channel.ee: org.jboss.msc.service.StartException in service org.wildfly.clustering.jgroups.channel.ee: java.lang.IllegalStateException: java.lang.Exception: failed to open a port in range 55200-55200 (last exception: java.net.BindException: アドレスは既に使用中です) at org.wildfly.clustering.service@26.1.2.Final//org.wildfly.clustering.service.FunctionalService.start(FunctionalService.java:66) at org.wildfly.clustering.service@26.1.2.Final//org.wildfly.clustering.service.AsyncServiceConfigurator$AsyncService.lambda$start$0(AsyncServiceConfigurator.java:117) at org.jboss.threads@2.4.0.Final//org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1990) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486) at org.jboss.threads@2.4.0.Final//org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377) at java.base/java.lang.Thread.run(Thread.java:833) at org.jboss.threads@2.4.0.Final//org.jboss.threads.JBossThread.run(JBossThread.java:513) Caused by: java.lang.IllegalStateException: java.lang.Exception: failed to open a port in range 55200-55200 (last exception: java.net.BindException: アドレスは既に使用中です) at org.jboss.as.clustering.jgroups@26.1.2.Final//org.jboss.as.clustering.jgroups.subsystem.ChannelServiceConfigurator.get(ChannelServiceConfigurator.java:116) at org.jboss.as.clustering.jgroups@26.1.2.Final//org.jboss.as.clustering.jgroups.subsystem.ChannelServiceConfigurator.get(ChannelServiceConfigurator.java:58) at org.wildfly.clustering.service@26.1.2.Final//org.wildfly.clustering.service.FunctionalService.start(FunctionalService.java:63) ... 7 more
ここで、-Djboss.socket.binding.port-offset
を指定して起動しなおします。
$ java -Djboss.socket.binding.port-offset=1000 -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar
今度は起動に成功するので、動作確認してみましょう。
$ curl -b cookie.txt -c cookie.txt localhost:8080/hello Hello[2022-10-19T00:04:39.439503952] $ curl -b cookie.txt -c cookie.txt localhost:9080/hello Hello[2022-10-19T00:04:39.439503952] $ curl -b cookie.txt -c cookie.txt localhost:8080/hello Hello[2022-10-19T00:04:39.439503952] $ curl -b cookie.txt -c cookie.txt localhost:9080/hello Hello[2022-10-19T00:04:39.439503952]
OKですね。クラスタリングもうまくいってみます。
これで、今回のお題の確認は終わりました。
ヘルプを見てみる
ヘルプを見てみます。
$ java -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar --help
ふつうに表示されて、ちょっと面白いです。
Usage: java -jar <bootable jar> [args...] where args include: --deployment=<value> Path to deployment artifact (war,jar,ear or exploded deployment dir) to deploy in hollow jar -b=<value> Set system property jboss.bind.address to the given value -b<interface>=<value> Set system property jboss.bind.address.<interface> to the given value -D<name>[=<value>] Set a system property --cli-script=<value> Path to a CLI script to execute when starting the Bootable JAR --display-galleon-config Display the content of the Galleon configuration used to build this bootable JAR --help Display this message and exit --install-dir=<value> Path to directory in which the server is installed. By default the server is installed in TEMP directory. --properties=<url> Load system properties from the given url -secmgr Activate the SecurityManager -S<name>[=<value>] Set a security property -u=<value> Set system property jboss.default.multicast.address to the given value --version Print version and exit
java -jar
で実行するので-D
で指定するシステムプロパティは-jar
よりも前の指定になりますが
$ java -Djboss.http.port=9080 -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar
その他の引数を指定する場合は、コマンドライン引数として指定することになります。
$ java -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar -b=192.168.0.6
それはそうと、--version
でバージョンが見られるのが個人的にはちょっと意表を突かれた感じがしておもしろかった(?)です。
$ java -jar target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar --version WildFly Full 26.1.2.Final (WildFly Core 18.1.2.Final)
どうなっている?
ところで、-Djboss.socket.binding.port-offset
などがふつうに使えましたが、どうなっているんでしょう?
standalone.xml
でも入っているのかなと思い、Bootable JARからXMLファイルを探してみます。
$ unzip -l target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar | grep xml
standalone.xml
ファイルは入っていないのですが、provisioning.xml
というファイルがあったのでこちらを見てみます。
$ unzip -p target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar provisioning.xml <?xml version="1.0" ?> <installation xmlns="urn:jboss:galleon:provisioning:3.0"> <feature-pack location="wildfly@maven(org.jboss.universe:community-universe)#26.1.2.Final"> <default-configs inherit="false"/> <packages inherit="false"/> </feature-pack> <config model="standalone" name="standalone.xml"> <layers> <include name="jaxrs"/> <include name="web-clustering"/> </layers> </config> <options> <option name="optional-packages" value="passive+"/> </options> </installation>
WildFly Bootable JARを作成するためにWildFly JAR Maven Pluginに指定した内容が、ほぼ入っている感じですね。
で、stanalone.xml
から指定したレイヤーだけ使っている感じです。
<config model="standalone" name="standalone.xml"> <layers> <include name="jaxrs"/> <include name="web-clustering"/> </layers> </config>
そして、作成されたJARファイルの中を見ていると、wildfly.zip
というひときわ大きなファイルがあります。
$ unzip -l target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar | grep wildfly.zip 90700689 2022-10-19 00:04 wildfly.zip
ちなみに、今回作成したJARファイルは87Mでした。
$ ll -h target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar -rw-rw-r-- 1 xxxxx xxxxx 87M 10月 19 00:04 target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar
wildfly.zip
を取り出してみます。
$ unzip target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar wildfly.zip Archive: target/wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT-bootable.jar inflating: wildfly.zip
今回のBootable JARは、ほぼwildfly.zip
のサイズですね。
$ ll -h wildfly.zip -rw-rw-r-- 1 xxxxx xxxxx 87M 10月 19 00:04 wildfly.zip
中身は、サイズが小さくなったWildFlyみたいですね。WildFly JAR Maven Pluginで指定したレイヤーが必要とする程度のサイズになっている
ような気がします。
standalone.xml
を取り出してみます。
$ unzip wildfly.zip standalone/configuration/standalone.xml Archive: wildfly.zip inflating: standalone/configuration/standalone.xml
standalone.xml
の最後の方を見ると、今回作成したWARファイルがデプロイされる設定になっています。
<deployments> <deployment name="wildfly-bootable-jar-clustering-0.0.1-SNAPSHOT.war" runtime-name="ROOT.war"> <content sha1="6c47a2feb9d4b149c7b26dfbfb7e172646d6e6ed"/> </deployment> </deployments>
ということは、こちらがWildFly Bootable JARで起動されるWildFlyの実体なんでしょうね。
standalone.xml
自体は通常のWildFlyのものとほとんど変わらないようですね。
以下はwildfly.zip
に含まれていたstandalone.xml
のsocket-binding-group
の抜粋です。
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}"> <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/> <socket-binding name="http" port="${jboss.http.port:8080}"/> <socket-binding name="https" port="${jboss.https.port:8443}"/> <socket-binding name="jgroups-mping" interface="private" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45700"/> <socket-binding name="jgroups-tcp" interface="private" port="7600"/> <socket-binding name="jgroups-tcp-fd" interface="private" port="57600"/> <socket-binding name="jgroups-udp" interface="private" port="55200" multicast-address="${jboss.default.multicast.address:230.0.0.4}" multicast-port="45688"/> <socket-binding name="jgroups-udp-fd" interface="private" port="54200"/> <socket-binding name="txn-recovery-environment" port="4712"/> <socket-binding name="txn-status-manager" port="4713"/> </socket-binding-group>
standalone.xml
内で、レイヤーで使えるようにしている範囲は起動時にシステムプロパティで変更できそうです。今回もそれを利用しましたし。
なんとなく雰囲気がわかったので、今回はこのあたりでOKかなと思います。
構成をもっと大きく変えたい場合は?
システムプロパティや起動引数の範囲ではなく、そもそもサブシステムの設定等を変えたい場合はこちらを参照、ですね。
- WildFly Bootable JAR Documentation / Configuring the server during packaging
- WildFly Bootable JAR Documentation / Configuring the server at runtime
まとめ
今回は、WildFly Bootable JARで作成したアプリケーションの起動時に、システムプロパティや起動引数が指定できたりするのか?WildFlyと
どう違うのか?という点でちょっと見てみました。
割とそのままでしたね。
ちょっと気にしすぎた感じもしますが、これで確認できたので今後は安心して使えそうです。