以下の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/02/02/232604より取得しました。


Maven War PluginのfailOnMissingWebXmlのデフォルト値がプロジェクトの依存関係で変わるという話

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

このところ、WildFlyを使ったりしている時に毎回毎回Maven War Pluginの設定を書いていたのですが、その理由は
failOnMissingWebXmlpropertiesに書いても効かなくなっていたからです。

    <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>

とはいえ、Maven War Pluginを毎回書くのも微妙だなぁと思ってどうしたらいいのか少し調べてみました。

Maven War Plugin 3.1.0から、failOnMissingWebXmlのデフォルト値の動きが変わっていたという話

Maven War Pluginのwar:warゴールにあるfailOnMissingWebXmlの説明を見ると、プロジェクトの依存関係に
Servlet 3.0より新しいAPIに依存しているかどうかで、デフォルト値が変わると書かれています。

Starting with 3.1.0, this property defaults to false if the project depends on the Servlet 3.0 API or newer.

war:war / Parameter Details / failOnMissingWebXml

早い話が、プロジェクトの依存関係にServlet 3.0以上があるとデフォルト値がfalseになるということですね。

それはそうと、properties直下で指定した時に効かなくなったのが気になるのですが、このあたりが怪しいですね。

[MWAR-366] Change package to org.apache.maven.plugins to prevent conf… · apache/maven-war-plugin@4ec3d60 · GitHub

Mavenのコアとパッケージ名が衝突していたので、リネームしたんですって。
この挙動はMaven War Plugin 3.0以降でしょうか?

どちらにしてももう効かないみたいなので、あまり過去に遡ろうとは思いませんが。

では、少し確認してみましょう。

環境

今回の環境はこちら。

$ java --version
openjdk 21.0.5 2024-10-15
OpenJDK Runtime Environment (build 21.0.5+11-Ubuntu-1ubuntu124.04)
OpenJDK 64-Bit Server VM (build 21.0.5+11-Ubuntu-1ubuntu124.04, mixed mode, sharing)


$ mvn --version
Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937)
Maven home: $HOME/.sdkman/candidates/maven/current
Java version: 21.0.5, vendor: Ubuntu, runtime: /usr/lib/jvm/java-21-openjdk-amd64
Default locale: ja_JP, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-52-generic", arch: "amd64", family: "unix"

サンプルコード

確認用のWARプロジェクトを作成します。

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>war-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-core</artifactId>
            <version>6.2.11.Final</version>
        </dependency>
        <dependency>
            <groupId>org.jboss.resteasy</groupId>
            <artifactId>resteasy-servlet-initializer</artifactId>
            <version>6.2.11.Final</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>ROOT</finalName>
    </build>
</project>

動作確認用にRESTEasyを依存関係に加えていますが、RESTEasyの推移的依存関係にServlet APIは現れません。
以下はmvn dependency:treeの結果です。

[INFO] --- dependency:3.7.0:tree (default-cli) @ war-test ---
[INFO] org.littlewings:war-test:war:0.0.1-SNAPSHOT
[INFO] +- org.jboss.resteasy:resteasy-core:jar:6.2.11.Final:compile
[INFO] |  +- org.jboss.logging:jboss-logging:jar:3.5.3.Final:compile
[INFO] |  +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile
[INFO] |  +- jakarta.ws.rs:jakarta.ws.rs-api:jar:3.1.0:compile
[INFO] |  +- jakarta.xml.bind:jakarta.xml.bind-api:jar:3.0.1:compile
[INFO] |  +- org.jboss:jandex:jar:2.4.5.Final:compile
[INFO] |  +- org.jboss.resteasy:resteasy-core-spi:jar:6.2.11.Final:compile
[INFO] |  +- org.reactivestreams:reactive-streams:jar:1.0.4:compile
[INFO] |  +- jakarta.activation:jakarta.activation-api:jar:2.1.3:compile
[INFO] |  +- org.eclipse.angus:angus-activation:jar:2.0.2:compile
[INFO] |  +- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile
[INFO] |  \- com.ibm.async:asyncutil:jar:0.1.0:compile
[INFO] \- org.jboss.resteasy:resteasy-servlet-initializer:jar:6.2.11.Final:compile
[INFO] ------------------------------------------------------------------------

Jakarta RESTful Web Servicesのコードも加えておきますが、動作確認は省略します。

src/main/java/org/littlewings/war/HelloResource.java

package org.littlewings.war;

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";
    }
}

src/main/java/org/littlewings/war/RestApplication.java

package org.littlewings.war;

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

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

web.xmlは用意していません。

いろいろ設定を変えて試してみる

まずpropertiesfailOnMissingWebXmlを追加してみます。

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

パッケージング。

$ mvn package

Maven War Pluginについては特になにも指定していませんが、Apache Maven 3.9.9ではMaven War Plugin 3.4.0が
動作するようです。

[INFO] --- war:3.4.0:war (default-war) @ war-test ---

で、これは失敗します。

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:3.4.0:war (default-war) on project war-test: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

いったんpropertiesに追加したfailOnMissingWebXmlは削除。

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

Maven War Pluginを明示的に追加し、ここにfailOnMissingWebXmlを設定。

    <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>
        </plugins>
    </build>

今度は成功します。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

ですが、これだけのために前は書いていなかったMaven War Pluginを追加したくないな、と。

ここで、Maven War Pluginの設定をコメントアウト

        <!--
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
        -->

プロジェクトの依存関係に、Jakarta Servletを追加します。

        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
            <scope>provided</scope>
        </dependency>

すると、ビルドができるようになります。

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

確かにデフォルト値が変わっているようです。

どうやって判定しているかというと、プロジェクトのクラスパス上にjavax.servlet.annotation.WebServletまたは
jakarta.servlet.annotation.WebServletがあるかどうかを見ているようです。

https://github.com/apache/maven-war-plugin/blob/maven-war-plugin-3.4.0/src/main/java/org/apache/maven/plugins/war/WarMojo.java#L276-L312

というわけで、Jakarta Servletへの依存関係は入れておいた方がよさそうですね。

おわりに

Maven War PluginのfailOnMissingWebXmlの挙動でちょっと困っていた、という話でした。

前のようにfailOnMissingWebXmlpropertiesの直下に書いても効かなくなったのはちょっと扱いにくくなりましたが、
仕方ないかなと。

最近、Jakarta EEのAPIを使ってWebアプリケーションを書いている時はJakarta RESTful Web Servicesや
Jakarta Contexts and Dependency Injectionなどを依存関係に書いても、Jakarta Servletを明示的に書くことは
少なかったので、よくこの問題を踏んでいたんですよね。

特になにも考えずにMaven War Pluginの設定をしていたのですが、今後はJakarta Servletを依存関係に入れるように
していきましょう。Jakarta Servletが使えないランタイム上で使うことはそうそうないと思いますし、そもそも
Jakarta Servletが使えない環境下だと扱うのはWARファイルではないでしょう。




以上の内容はhttps://kazuhira-r.hatenablog.com/entry/2025/02/02/232604より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14