maven tips : Springのmavenプラグインによるrepackageゴールの簡略化

Java

以下のサイトを参考に、repackageゴールを少し便利に実行する方法を調査したのでまとめてみた。

Spring Boot Maven Plugin Documentation

mavenでSpring Bootアプリケーションのfat-jarの作成方法は以下にまとめた通り、「spring-boot-starter-parent」にはすでに「repackage」ゴールが定義されているため、mvn コマンドにて「spring-boot:repackage」を指定する事で作成できる。

ただし、このままでは「mvn pakcage spring-boot:repackage」という少し長いコマンドを実行しないと正しくrepackageは実行されない。

ここでは「spring-boot-maven-plugin」により、mavenの標準フェーズ「package」に「repackage」を関連づけし、「package」実行時に「repackage」も実行するようにpom.xmlを更新する。

maven pluginとは

まずmaven自体がpluginを実行するためのコアフレームワークという前提があり、mavenで実行するbuildもしくはpackagingの各タスクはpluginのコレクションで構成されている。

各pluginは、buildで使用するか、reportingで使用するかが意図されて作成されている。

Maven – Introduction to Maven Plugin Development

各pluginはmojo(Maven plain Old Java Objectの略)形式のクラスライブラリで、mavenにて実行できるゴールを定義したもの。

1つのmojoには1つのゴールが定義され、それがjarでコレクション化されている。

例えば、spring-boot-maven-pluginは、buildで使われるように構築されたpluginで、複数のmojo(ゴール)で構成されたjarファイルとなっている。

Spring Boot Maven Plugin Documentation

pom.xmlのbuildタグとは

when to use plugin in maven pom.xml?
In our project, we have configured jetty inside build plugin in pom, i want to understand configuration settings in pom/...

mavenのpluginには「build plugin」と「reporting plugin」という2種類のpluginがある。

build pluginは、アーティファクト(通常はjar or war)のbuild時に特定のフェーズに関連づけたゴールを実行するためのプラグインであり、reporting pluginは、プロジェクトのサイト情報を生成する時に、サイト情報の生成の一部として実行するためのプラグイン。

Maven – Available Plugins

今回使用するspring-boot-maven-pluginはbuild時にjarをrepackageするためのpluginなので、buildタグの中に定義する。

使いたいpluginのgroupIdやartifactIdを調べる

様々なサイトでspring boot maven pluginをpom.xmlに定義しているサンプルを見るが、そもそも使いたいpluginがある場合、「groupId」「artifactId」「version」をどのように確認すれば良いか。

その情報はmaven central repositoryサイトで調べる事ができる。

Maven Central
Official search by the maintainers of Maven Central Repository.

今回利用する「spring-boot-maven-plugin」の情報を検索すると以下のように表示された。先ほど作成したpom.xmlに定義した情報はこのようにして得る事ができる。

更新したpom.xml

上記の各情報を元に、更新前と更新後のpom.xmlを掲載する。

以下、更新前の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> <https://maven.apache.org/POM/maven-4.0.0.xsd>">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
    </parent>

    <!-- Additional lines to be added here... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

そして以下が更新後の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> <https://maven.apache.org/POM/maven-4.0.0.xsd>">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
    </parent>

    <!-- Additional lines to be added here... -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

	<!-- ここにpluginを追加-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

ちなみに、上記の記述により、「mvn package」を実行すると「repackage」が自動的に実行されるが、さまざまなサイトで紹介されているpom.xmlは以下のようになっている。これを実行すると実行ログからrepackageが2回実行されていたため、余計なタスクが実行されている事がわかり、私は上記のようにpluginの定義だけとした。

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
				<!-- 以降の定義があるとrepackageが重複して実行されてしまう -->
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

実行ログ

以下にspring-boot-maven-pluginを指定して「mvn package」を実行した時の結果をログする。

$ mvn package
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------< com.example:myproject >------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- resources:3.3.1:resources (default-resources) @ myproject ---
[INFO] skip non existing resourceDirectory /Users/sato/proj/learn/java/SpringTips/getstartedapp/src/main/resources
[INFO] skip non existing resourceDirectory /Users/sato/proj/learn/java/SpringTips/getstartedapp/src/main/resources
[INFO] 
[INFO] --- compiler:3.11.0:compile (default-compile) @ myproject ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- resources:3.3.1:testResources (default-testResources) @ myproject ---
[INFO] skip non existing resourceDirectory /Users/sato/proj/learn/java/SpringTips/getstartedapp/src/test/resources
[INFO] 
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ myproject ---
[INFO] No sources to compile
[INFO] 
[INFO] --- surefire:3.1.2:test (default-test) @ myproject ---
[INFO] 
[INFO] --- jar:3.3.0:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/sato/proj/learn/java/SpringTips/getstartedapp/target/myproject-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot:3.2.2:repackage (repackage) @ myproject ---
[INFO] Replacing main artifact /Users/sato/proj/learn/java/SpringTips/getstartedapp/target/myproject-0.0.1-SNAPSHOT.jar with repackaged archive, adding nested dependencies in BOOT-INF/.
[INFO] The original artifact has been renamed to /Users/sato/proj/learn/java/SpringTips/getstartedapp/target/myproject-0.0.1-SNAPSHOT.jar.original
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.580 s
[INFO] Finished at: 2024-01-29T18:42:07+09:00
[INFO] ------------------------------------------------------------------------

なぜpackage実行時にrepackageが実行されるのか

それは、以下リンク先に記載がある通り、デフォルトでrepackageゴールがpackageフェーズに関連づけされているから。

Spring Boot Maven Plugin – spring-boot:repackage

まとめ

pom.xmlにspring-boot-maven-pluginを定義し、repackageゴールを実行するように定義する事で、mvn packageを実行するとrepackageも実行され、java -jarコマンドで実行可能なjarファイルが生成される。

これが常に必要という事ではなく、以下のように使い分けする必要があると思う。今後どのように定義すれば1つのpom.xmlでこれらの用途でbuildできるjarを分ける事ができるか確認したい。

  • java -jarで実行できるfat-jarの作成
  • 他プロジェクトから参照されるライブラリとしてのjarの作成

コメント

タイトルとURLをコピーしました