What's?
Jetty Maven Pluginを使うと、開発中にホット再デプロイメントができるらしいので試してみました。
Jetty Maven Plugin
Jetty Maven Pluginのドキュメントはこちら。
ホット再デプロイメントについては、jetty:run
ゴールやjetty:run-war
ゴールでscan
プロパティに値を設定すると有効にできます。
scan
The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. By default this is -1, which disables hot redeployment scanning. A value of 0 means no hot redeployment is done, and that you must use the Enter key to manually force a redeploy. Any positive integer will enable hot redeployment, using the number as the sweep interval in seconds.
デフォルトは-1
で無効化されていて、0
を指定するとEnterキーで実行させることになります。
正の整数を指定すると、その間隔でホット再デプロイメント対象をスキャンするようです。
スキャン対象は、jetty:run
ゴールの場合は以下のディレクトリです。
- resources in
${project.basedir}/src/main/webapp
- classes in
${project.build.outputDirectory}
- web.xml in
${project.basedir}/src/main/webapp/WEB-INF/
jetty:run-war
の場合はWARファイルですね。
今回はjetty:run
で試してみたいと思います。
環境
今回の環境はこちら。
$ java --version
openjdk 17.0.10 2024-01-16
OpenJDK Runtime Environment (build 17.0.10+7-Ubuntu-122.04.1)
OpenJDK 64-Bit Server VM (build 17.0.10+7-Ubuntu-122.04.1, mixed mode, sharing)
$ mvn --version
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae)
Maven home: /home/charon/.sdkman/candidates/maven/current
Java version: 17.0.10, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "5.15.0-101-generic", arch: "amd64", family: "unix"
サンプルアプリケーション
Jerseyを使って、簡単なJakarta RESTful Web Services(JAX-RS)アプリケーションを書いて試すことにします。
<?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>jetty-reload-example</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>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>3.1.5</version>
</dependency>
</dependencies>
<build>
<finalName>ROOT</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>12.0.7</version>
</plugin>
</plugins>
</build>
</project>
package org.example.web;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
import java.util.Set;
@ApplicationPath("")
public class ApplicationConfig extends Application {
@Override
public Set<Class<?>> getClasses() {
return Set.of(HelloResource.class);
}
}
package org.example.web;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("hello")
public class HelloResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String message() {
return "Hello World";
}
}
まずは動作確認。Jettyを起動。
$ mvn jetty:run
確認。
$ curl localhost:8080/hello
Hello World
ここからは、Jetty Maven Pluginのscan
の設定と
<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>12.0.7</version>
<configuration>
<scan>...</scan>
</configuration>
</plugin>
以下のメッセージの部分を変えて確認してみましょう。
@GET
@Produces(MediaType.TEXT_PLAIN)
public String message() {
return "Hello World";
}
Jetty Maven Pluginのホット再デプロイメントを試す
では、Jetty Maven Pluginのホット再デプロイメントを試してみます。
ここからは、`jetty:runPゴールで起動中に
$ mvn jetty:run
以下の部分を
@GET
@Produces(MediaType.TEXT_PLAIN)
public String message() {
return "Hello World";
}
メッセージの末尾に!!
を追加して確認しているものとします。
@GET
@Produces(MediaType.TEXT_PLAIN)
public String message() {
return "Hello World!!";
}
デフォルト(無効化)
まずはデフォルトから。scan
を-1
にしている状態と同義です。
<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>12.0.7</version>
</plugin>
この場合、起動時にホット再デプロイメントが無効化されていることがログ出力されます。
[INFO] Automatic redeployment disabled, see 'mvn jetty:help' for more redeployment options
なので、コンパイルしても
$ mvn compile
変更は反映されません。
$ curl localhost:8080/hello
Hello World
scanを0に設定する
次は、scan
を0
に設定します。
<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>12.0.7</version>
<configuration>
<scan>0</scan>
</configuration>
</plugin>
これでjetty:run
で起動すると、ログにEnterで再デプロイメントが行われることが出力されます。
Hit <enter> to redeploy:
ここで、ソースコード変更の後にコンパイルして
$ mvn compile
jetty:run
を実行しているターミナルでEnterを押すと再デプロイメントが行われます。
[INFO] Restarting oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Classes = /path/to/jetty-reload-example/target/classes
[INFO] Stopped oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STOPPED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Context path = /
[INFO] Tmp directory = /path/to/jetty-reload-example/target/tmp
[INFO] web.xml file = null
[INFO] Webapp directory = /path/to/jetty-reload-example/target/webapp-synth
[INFO] Web defaults = org/eclipse/jetty/ee10/webapp/webdefault-ee10.xml
[INFO] Web overrides = none
[INFO] Started oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
3月 28, 2024 1:03:47 午後 org.glassfish.jersey.message.internal.MessagingBinders$EnabledProvidersBinder bindToBinder
警告: A class jakarta.activation.DataSource for a default provider MessageBodyWriter<jakarta.activation.DataSource> was not found. The provider is not available.
3月 28, 2024 1:03:47 午後 org.glassfish.jersey.server.wadl.WadlFeature configure
警告: JAX-B API not found . WADL feature is disabled.
[INFO] Started oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Restart completed at Thu Mar 28 13:03:47 JST 2024
変更が反映されました。
$ curl localhost:8080/hello
Hello World!!
コンパイルが必要なのは、スキャン対象が以下だからですね。
- resources in
${project.basedir}/src/main/webapp
- classes in
${project.build.outputDirectory}
- web.xml in
${project.basedir}/src/main/webapp/WEB-INF/
scanを正の整数に設定する
最後は、scan
を正の整数に設定してみます。今回は5秒にしてみました。
<plugin>
<groupId>org.eclipse.jetty.ee10</groupId>
<artifactId>jetty-ee10-maven-plugin</artifactId>
<version>12.0.7</version>
<configuration>
<scan>5</scan>
</configuration>
</plugin>
jetty:run
で起動すると、5秒に1度スキャンすることを示すログが出力されます。
[INFO] Scan interval sec = 5
ここでソースコードを変更し、先ほどと同様コンパイルすると
$ mvn compile
今度は自動検出して再デプロイメントが行われます。この間隔をscan
で指定するわけですね。
[INFO] Restarting oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Classes = /path/to/jetty-reload-example/target/classes
[INFO] Stopped oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STOPPED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Context path = /
[INFO] Tmp directory = /path/to/jetty-reload-example/target/tmp
[INFO] web.xml file = null
[INFO] Webapp directory = /path/to/jetty-reload-example/target/webapp-synth
[INFO] Web defaults = org/eclipse/jetty/ee10/webapp/webdefault-ee10.xml
[INFO] Web overrides = none
[INFO] Started oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Started oeje10mp.MavenWebAppContext@dbed7fd{ROOT,/,b=file:///path/to/jetty-reload-example/target/webapp-synth/,a=AVAILABLE,h=oeje10s.SessionHandler@113dcaf8{STARTED}}{file:///path/to/jetty-reload-example/target/webapp-synth/}
[INFO] Restart completed at Thu Mar 28 13:08:46 JST 2024
結果は、0秒を指定した時と同じなので割愛します。