Maven Assembly Plugin をマルチモジュールプロジェクトで使う

Maven3 のようなマルチモジュールプロジェクトで Maven Assembly Plugin を使う方法を記しておきます。日本語の情報少ないので。

Maven Assembly Plugin とは

Maven Assembly Plugin は、よくある zip や tar.gz などでプロジェクトの成果物を配布用にパッケージングする Maven プラグインです。

マルチモジュールプロジェクトの作成

ここでは1つの jar と1つの war を作成するマルチモジュールプロジェクトで Maven Assembly Plugin を使うものとします。
まずは親プロジェクトを作成します。親プロジェクトは単なる束ね役なのでarchetype には maven-archetype-site-simple を指定します。以下のコマンドで親プロジェクトを作成します(実際には1行です)。

mvn archetype:create -DarchetypeArtifactId=maven-archetype-site-simple 
    -DartifactId=sample -DgroupId=etc9.sample -Dversion=1.0


作成されたプロジェクトに移動し、

cd sample


子となる2つのプロジェクトを作成します。

mvn archetype:create -DgroupId=etc9.sample -DartifactId=sample-core -Dversion=1.0
mvn archetype:create -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=etc9.sample
    -DartifactId=sample-webapp -Dversion=1.0


この時点で、親プロジェクトの pom.xml には modules 要素として2つの子プロジェクトが追加されます。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ・・・略
  <modelVersion>4.0.0</modelVersion>

  <groupId>etc9.sample</groupId>
  <artifactId>sample</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>

  <modules>
    <module>sample-core</module>
    <module>sample-webapp</module>
  </modules>
</project>

packaging として pom が指定されていることに注意してください。


また、子プロジェクトの pom.xml には、親プロジェクトの指定が追加されています。

  <parent>
    <artifactId>sample</artifactId>
    <groupId>etc9.sample</groupId>
    <version>1.0</version>
  </parent>

これにより、親 pom と子 pom の階層構造が作られ、各種設定当が親から子へと連鎖する形となります。


この時点でのディレクトリ構成は以下のようになります。

sample
├─ sample-core
│  └─ pom.xml
├─ sample-webapp
│  └─ pom.xml
└─ pom.xml

依存関係の定義

ここで話がわき道にそれますが、pom の親子関係を利用して、依存ライブラリの定義を親 pom で一括して行っておきます。親プロジェクトの pom.xml に sample-core と、sample-webapp commons-lang の依存ライブラリの定義を追加したとします。

<project>
  ...
  <properties>
    <commonsLangVersion>2.0</commonsLangVersion>
  </properties>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>etc9.sample</groupId>
        <artifactId>sample-core</artifactId>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>etc9.sample</groupId>
        <artifactId>sample-webapp</artifactId>
        <version>${project.version}</version>
        <type>war</type>
      </dependency>
      <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>${commonsLangVersion}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  ...
</project>


親 pom.xml にて dependencyManagement 要素に指定したライブラリは、子 pom 内で指定する場合にバージョン指定を行わずに済ませることができます。そのため子pomでは以下のようにバージョン指定が不要になります。

<project>
  ...
  <dependencies>
   <dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
   </dependency>
  </dependencies>
  ...
</project>


一方、親 pom にて以下のように dependencies 要素に直接定義した場合には、そのまま子 pom に定義が継承されます。よって子pomでの依存ライブラリの指定は不要となります。

<project>
  ...
  <properties>
    <junitVersion>4.8.2</junitVersion>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junitVersion}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  ...
</project>


上記の内容は plugin 要素についても同様の考え方です。以下の例では、maven-assembly-plugin については pluginManagement 要素にてプラグイン定義のみ行っているため使用するかしないかは子pomでの設定次第となります。
maven-compiler-plugin については親 pom の plugins 要素として定義してあるため、子 pom では明示的に宣言する必要がなくなります。

<project>
  ...
  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.0.2</version>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
        </plugin>
    </plugins>
  </build>
  ...
</project>

Maven Assembly Plugin の設定

シングルプロジェクトであれば問題はないのですが、マルチモジュールプロジェクトの場合、モジュール間の依存関係があるため、配布物作成用に新しいモジュールを作成する必要があります。
以下のコマンドにて sample-distribution モジュールを作成します。archetype は何でもよいですが、pom として作成される maven-archetype-site-simple にしておきます。

mvn archetype:create -DarchetypeArtifactId=maven-archetype-site-simple -DartifactId=sample-distribution
    -DgroupId=etc9.sample -Dversion=1.0


この時点でのディレクトリ構成は以下のようになります。

sample
├─ sample-core
│  └─ pom.xml
├─ sample-webapp
│  └─ pom.xml
├─ sample-distribution
│  └─ pom.xml
└─ pom.xml


親 pom のプラグイン定義に maven-assembly-plugin を追加します。親 pom の全内容は以下となります。

<?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>etc9.sample</groupId>
  <artifactId>sample</artifactId>
  <version>1.0</version>
  <packaging>pom</packaging>

  <properties>
    <junitVersion>4.8.2</junitVersion>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <modules>
    <module>sample-core</module>
    <module>sample-webapp</module>
    <module>sample-distribution</module>
  </modules>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>etc9.sample</groupId>
        <artifactId>sample-core</artifactId>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>etc9.sample</groupId>
        <artifactId>sample-webapp</artifactId>
        <version>${project.version}</version>
        <type>war</type>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junitVersion}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-assembly-plugin</artifactId>
          <version>2.2-beta-5</version>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.0.2</version>
          <configuration>
            <source>1.5</source>
            <target>1.5</target>
          </configuration>
        </plugin>
    </plugins>
  </build>

</project>

distribution モジュールの定義

最後に作成した sample-distribution モジュールの pom を編集していきます。親 pom では pluginManagement として maven-assembly-plugin を定義しているので、子である sample-distribution モジュールにて各定義を記述していきます。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <id>create-distribution</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptors>
                <descriptor>src/main/assembly/bin.xml</descriptor>
                <descriptor>src/main/assembly/src.xml</descriptor>
              </descriptors>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

上記では、executions にてフェーズを package として定義しています。これにより、package フェーズにて maven-assembly-plugin が動作することになります。
また、configuration では src/main/assembly/bin.xml として配布物作成のための Assembly Descriptor を別ファイルとして指定しています。Assembly Descriptor の定義については以下となります。
http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html


ここでは基本的な定義のみ記載します。以下はバイナリファイル作成用の Assembly Descriptor(src/main/assembly/bin.xml ) となります。

<assembly>
  <id>bin</id>
  <formats>
    <format>zip</format>
  </formats>
  <includeBaseDirectory>true</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <useProjectArtifact>false</useProjectArtifact>
      <outputDirectory>lib</outputDirectory>
      <excludes>
        <exclude>junit:junit</exclude>
      </excludes>
    </dependencySet>
  </dependencySets>

  <fileSets>
    <fileSet>
      <includes>
        <include>README*</include>
        <include>LICENSE*</include>
        <include>NOTICE*</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>src/bin</directory>
      <outputDirectory>bin</outputDirectory>
      <includes>
        <include>*.bat</include>
        <include>*.conf</include>
      </includes>
      <lineEnding>dos</lineEnding>
    </fileSet>
    <fileSet>
      <directory>src/conf</directory>
      <outputDirectory>conf</outputDirectory>
    </fileSet>
  </fileSets>
</assembly>

成果物(ここでは jar ファイルと war ファイル)を lib フォルダに出力するように定義しています。合わせて src/bin や src/conf の内容(sample-distribution モジュール内に作成したもの)を配布ファイルに含めるように指定しています。


次にソースファイル作成用の Assembly Descriptor(src/main/assembly/src.xml ) となります。

<assembly>
  <id>src</id>
  <formats>
    <format>zip</format>
  </formats>
  <fileSets>
    <fileSet>
      <directory>${project.basedir}/..</directory>
      <outputDirectory>/</outputDirectory>
      <excludes>
        <exclude>%regex[(?!((?!target/)[^/]+/)*src/).*target.*]</exclude>
        <exclude>**/*.log</exclude>
      </excludes>
    </fileSet>
    <fileSet>
      <directory>${project.build.directory}/maven-shared-archive-resources/META-INF</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>DEPENDENCIES</include>
      </includes>
    </fileSet>
    <fileSet>
      <directory>${project.basedir}</directory>
      <outputDirectory>/</outputDirectory>
      <includes>
        <include>LICENSE.txt</include>
        <include>NOTICE.txt</include>
      </includes>
    </fileSet>
  </fileSets>
</assembly>


バイナリファイル、ソースファイルともに zip 形式で出力するように定義しています。

配布パッケージの作成

親プロジェクトで以下のコマンドを実行することで配布パッケージが作成されます。

mvn package


sample-distribution/target 以下にバイナリディストリビューションが作成されます。

sample-distribution-1.0-bin.zip
├─ lib
│  ├─ sample-core-1.0.jar
│  └─ sample-webapp-1.0.war
└─ ・・・

なお、sample-distribution の src/bin や src/conf などに配布すべきファイルを配置することでバイナリディストリビューションに含めることができます。


ソースディストリビューションは以下のような構成となります。親プロジェクト含めてパッケージングされています。

sample-distribution-1.0-src.zip
├─ sample-core
│  ├─ src
│  └─ pom.xml
├─ sample-distribution
│  ├─ src
│  └─ pom.xml
├─ sample-webapp
│  ├─ src
│  └─ pom.xml
└─ pom.xml