Maven Assembly Pluginで実現する高度な成果物構築
Maven Assembly Pluginは、Mavenプロジェクトのビルドプロセスにおいて、単一のデプロイ可能な成果物(配布物)を作成するための強力なツールです。単純なJARファイルやWARファイルだけでなく、依存関係を含む実行可能なスクリプト、スタンドアロンのアプリケーション、ドキュメント、設定ファイルなどをパッケージングし、複雑なプロジェクトのデプロイと配布を簡素化できます。この記事では、Maven Assembly Pluginの基本から高度な使い方までを網羅し、その活用方法を詳細に解説します。
1. はじめに:Maven Assembly Pluginとは
Mavenは、Javaプロジェクトのビルド、依存関係管理、ドキュメント生成などを自動化する強力なビルドツールです。Maven Assembly Pluginは、そのMavenの機能を拡張し、プロジェクトのビルドプロセスの中で、複数のファイル、ディレクトリ、依存関係などを組み合わせて、カスタムな成果物を生成します。
1.1 なぜAssembly Pluginが必要なのか
通常、MavenはJARファイルやWARファイルといった標準的な成果物を生成します。しかし、以下のようなシナリオでは、標準的な成果物だけでは不十分です。
- 実行可能なアプリケーション: 依存関係を含む実行可能なJARファイルを作成したい場合。
- スタンドアロンの配布物: 設定ファイル、ドキュメント、シェルスクリプトなどをすべて含む、単一の配布パッケージを作成したい場合。
- 複雑なディレクトリ構造: 特定のディレクトリ構造でファイル群をパッケージングする必要がある場合。
- 複数モジュールプロジェクト: 複数のモジュールから成果物を集約し、単一の配布物を作成したい場合。
- OS固有のパッケージ: Windows向けのZIPファイルやLinux向けのTAR.GZファイルなど、特定のOS向けのパッケージを作成したい場合。
Maven Assembly Pluginは、これらのニーズに対応し、複雑なプロジェクトのデプロイと配布を容易にします。
1.2 Assembly Pluginの基本的な仕組み
Assembly Pluginは、アセンブリ記述子 (Assembly Descriptor) と呼ばれるXMLファイルに基づいて動作します。アセンブリ記述子には、以下の情報が記述されています。
- アセンブリID: アセンブリの種類を識別するID (例:
jar-with-dependencies,dist)。 - フォーマット: 生成するアーカイブのフォーマット (例:
zip,tar.gz,jar)。 - ファイルセット: コピーするファイルやディレクトリの指定。
- 依存関係セット: プロジェクトの依存関係をどのように組み込むかの指定。
- モジュールセット: マルチモジュールプロジェクトにおけるモジュールの取り扱い。
Pluginは、アセンブリ記述子に従って、指定されたファイルやディレクトリ、依存関係などを集約し、指定されたフォーマットでアーカイブを生成します。
2. Maven Assembly Pluginの設定と基本
2.1 Pluginの依存関係を追加する
まずは、pom.xmlファイルにMaven Assembly Pluginの依存関係を追加する必要があります。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version> <!-- 最新のバージョンを確認してください -->
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
groupIdとartifactId: Maven Assembly Pluginを特定します。version: 使用するPluginのバージョンを指定します。最新バージョンを確認し、適宜変更してください。configuration: Pluginの動作をカスタマイズするための設定を行います。descriptors: アセンブリ記述子ファイルの場所を指定します。例では、src/main/assembly/assembly.xmlというファイルを指定しています。
executions: Pluginを実行するタイミングとゴールを指定します。id: 実行IDを定義します。phase: Mavenライフサイクルフェーズを指定します。packageフェーズでPluginを実行することで、JAR/WARファイルの作成後にアセンブリが生成されます。goals: 実行するゴールを指定します。singleゴールは、単一のアセンブリを作成するために使用されます。
2.2 アセンブリ記述子を作成する (assembly.xml)
上記の例では、src/main/assembly/assembly.xmlというアセンブリ記述子ファイルを使用しています。このファイルを作成し、アセンブリの構成を定義します。
xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>dist</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>/config</outputDirectory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
<id>: アセンブリのID。生成されるファイル名の一部になります。<formats>: 生成するアーカイブのフォーマットを指定します。例ではZIP形式を指定しています。<fileSets>: ファイルやディレクトリをコピーするための設定です。<directory>: コピー元ディレクトリを指定します。${project.basedir}はプロジェクトのルートディレクトリを表します。<outputDirectory>: コピー先のディレクトリを指定します。アーカイブ内の相対パスになります。例では、configディレクトリにファイルをコピーします。<includes>: コピーするファイルのパターンを指定します。例では、.propertiesと.xmlファイルをコピーします。
<dependencySets>: プロジェクトの依存関係を組み込むための設定です。<outputDirectory>: 依存関係をコピー先のディレクトリを指定します。アーカイブ内の相対パスになります。例では、libディレクトリに依存関係をコピーします。<scope>: 依存関係のスコープを指定します。runtimeスコープは、実行時に必要な依存関係のみをコピーします。
2.3 ビルドを実行する
設定が完了したら、Mavenのビルドを実行します。
bash
mvn clean package
ビルドが成功すると、targetディレクトリに、[artifactId]-[version]-dist.zipという名前のZIPファイルが生成されます。このZIPファイルには、src/main/resourcesディレクトリにある.propertiesと.xmlファイルがconfigディレクトリに、ランタイムスコープの依存関係がlibディレクトリにそれぞれ格納されています。
3. アセンブリ記述子の詳細
アセンブリ記述子は、アセンブリの構成を定義するための重要なファイルです。ここでは、アセンブリ記述子の各要素について詳しく解説します。
3.1 <assembly> (ルート要素)
アセンブリ記述子のルート要素です。名前空間とスキーマの場所を定義します。
3.2 <id>
アセンブリの一意なIDを定義します。このIDは、生成されるアーカイブのファイル名の一部として使用されます。
3.3 <formats>
生成するアーカイブのフォーマットをリストします。サポートされているフォーマットは、zip, tar, tar.gz, tar.bz2, jar, war, dirなどです。
3.4 <includeBaseDirectory> (オプション)
アーカイブのルートディレクトリを含めるかどうかを指定します。trueに設定すると、生成されるアーカイブのルートディレクトリに、プロジェクトのartifactIdとversionを組み合わせた名前のディレクトリが作成されます。デフォルトはtrueです。
3.5 <fileSets>
ファイルやディレクトリをコピーするための設定をリストします。
<fileSet>: 個々のファイルセットを定義します。<directory>: コピー元ディレクトリを指定します。<outputDirectory>: コピー先のディレクトリを指定します。<includes>: コピーするファイルのパターンを指定します。ANTスタイルのパターンを使用できます。<excludes>: コピーから除外するファイルのパターンを指定します。ANTスタイルのパターンを使用できます。<fileMode>: コピーするファイルのパーミッションを指定します (例:0644)。<directoryMode>: コピーするディレクトリのパーミッションを指定します (例:0755)。<filtered>: ファイルをフィルタリングするかどうかを指定します。trueに設定すると、Mavenのプロパティ (例:${project.version}) が展開されます。
3.6 <files>
単一のファイルをコピーするための設定をリストします。
<file>: 個々のファイルを定義します。<source>: コピー元ファイルを指定します。<outputDirectory>: コピー先のディレクトリを指定します。<destName>: コピー先のファイル名を指定します。<fileMode>: コピーするファイルのパーミッションを指定します (例:0644)。<filtered>: ファイルをフィルタリングするかどうかを指定します。trueに設定すると、Mavenのプロパティ (例:${project.version}) が展開されます。
3.7 <dependencySets>
プロジェクトの依存関係を組み込むための設定をリストします。
<dependencySet>: 個々の依存関係セットを定義します。<outputDirectory>: 依存関係をコピー先のディレクトリを指定します。<includes>: 含める依存関係を指定します。groupId:artifactIdの形式で指定します。<excludes>: 除外する依存関係を指定します。groupId:artifactIdの形式で指定します。<scope>: 依存関係のスコープを指定します (例:compile,runtime,provided).<useStrictFiltering>: 依存関係のフィルタリングを厳密に行うかどうかを指定します。trueに設定すると、includesとexcludesに一致しない依存関係はすべて除外されます。<outputFileNameMapping>: 依存関係のファイル名を変更するためのマッピングを指定します。例:${artifact.artifactId}-${artifact.version}.${artifact.extension}<unpack>: 依存関係を解凍するかどうかを指定します。trueに設定すると、依存関係 (JARファイルなど) が解凍されます。<unpackOptions>: 解凍オプションを指定します。<includes>: 解凍するファイルのパターンを指定します。<excludes>: 解凍から除外するファイルのパターンを指定します。
3.8 <moduleSets>
マルチモジュールプロジェクトにおけるモジュールを組み込むための設定をリストします。
<moduleSet>: 個々のモジュールセットを定義します。<includes>: 含めるモジュールを指定します。<excludes>: 除外するモジュールを指定します。<binaries>: モジュールのバイナリファイル (JARファイルなど) を組み込むための設定。<outputDirectory>: バイナリファイルをコピー先のディレクトリを指定します。<includes>: 含めるバイナリファイルを指定します。<excludes>: 除外するバイナリファイルを指定します。<outputFileNameMapping>: バイナリファイルのファイル名を変更するためのマッピングを指定します。
<sources>: モジュールのソースコードを組み込むための設定。<outputDirectory>: ソースコードをコピー先のディレクトリを指定します。<includes>: 含めるソースコードファイルを指定します。<excludes>: 除外するソースコードファイルを指定します。<fileMode>: ソースコードファイルのパーミッションを指定します (例:0644)。<directoryMode>: ソースコードディレクトリのパーミッションを指定します (例:0755)。
<resource>: モジュールのリソースファイルを組み込むための設定。<outputDirectory>: リソースファイルをコピー先のディレクトリを指定します。<includes>: 含めるリソースファイルを指定します。<excludes>: 除外するリソースファイルを指定します。<fileMode>: リソースファイルのパーミッションを指定します (例:0644)。<directoryMode>: リソースディレクトリのパーミッションを指定します (例:0755)。
4. 高度な使用例
4.1 実行可能なJARファイルを作成する (JAR with Dependencies)
依存関係を含む実行可能なJARファイルを作成するには、jar-with-dependenciesという記述子を使用します。
xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<componentDescriptors>
<componentDescriptor>src/main/assembly/executable-jar-component.xml</componentDescriptor>
</componentDescriptors>
</assembly>
この記述子では、すべての依存関係を解凍し、プロジェクトのJARファイルとリソースファイルをルートディレクトリに配置します。
さらに、マニフェストファイルを適切に設定するために、コンポーネント記述子を使用します。src/main/assembly/executable-jar-component.xmlを作成し、以下のように記述します。
“`xml
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
</manifest>
</archive>
</configuration>
“`
pom.xmlにmainClassを定義します。
xml
<properties>
<main.class>com.example.Main</main.class>
</properties>
これにより、[artifactId]-[version]-jar-with-dependencies.jarという実行可能なJARファイルが生成されます。
4.2 OS固有のパッケージを作成する
異なるOS向けのパッケージを作成するには、複数のアセンブリ記述子を使用し、プロファイルに基づいてアクティブ化します。
pom.xmlに以下のプロファイルを追加します。
xml
<profiles>
<profile>
<id>windows</id>
<activation>
<os>
<family>windows</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-windows.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>linux</id>
<activation>
<os>
<family>unix</family>
</os>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-linux.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
src/main/assembly/assembly-windows.xmlを作成し、Windows向けのZIPファイルを作成するように設定します。
xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>windows</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>/config</outputDirectory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
src/main/assembly/assembly-linux.xmlを作成し、Linux向けのTAR.GZファイルを作成するように設定します。
xml
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>linux</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/resources</directory>
<outputDirectory>/config</outputDirectory>
<includes>
<include>*.properties</include>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>
これにより、Windows環境では[artifactId]-[version]-windows.zipが、Linux環境では[artifactId]-[version]-linux.tar.gzが生成されます。
4.3 シェルスクリプトを実行可能にする
シェルスクリプトを実行可能にするには、fileMode属性を使用します。
xml
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/scripts</directory>
<outputDirectory>/bin</outputDirectory>
<includes>
<include>*.sh</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
</fileSets>
これにより、src/main/scriptsディレクトリにある.shファイルがbinディレクトリにコピーされ、実行可能になります。
4.4 依存関係のバージョンをファイル名に含める
依存関係のバージョンをファイル名に含めるには、outputFileNameMapping属性を使用します。
xml
<dependencySets>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<outputFileNameMapping>${artifact.artifactId}-${artifact.version}.${artifact.extension}</outputFileNameMapping>
<scope>runtime</scope>
</dependencySet>
</dependencySets>
これにより、依存関係のファイル名が[artifactId]-[version].[extension]の形式になります。
5. まとめ
Maven Assembly Pluginは、柔軟で強力なツールであり、様々なシナリオでカスタムな成果物を作成できます。この記事では、Maven Assembly Pluginの基本から高度な使い方までを網羅的に解説しました。
- 基本: Pluginの設定、アセンブリ記述子の作成、ビルドの実行。
- アセンブリ記述子の詳細: 各要素 (
<assembly>,<id>,<formats>,<fileSets>,<dependencySets>,<moduleSets>) の詳細な説明。 - 高度な使用例: 実行可能なJARファイルの作成、OS固有のパッケージの作成、シェルスクリプトの実行可能化、依存関係のバージョンをファイル名に含める。
これらの知識を活かして、Maven Assembly Pluginを最大限に活用し、プロジェクトのデプロイと配布を効率化してください。
6. トラブルシューティング
- アセンブリ記述子が見つからない:
pom.xmlの<descriptors>要素で指定されたパスが正しいか確認してください。 - 依存関係が正しく組み込まれない:
<scope>属性が正しいか確認してください。runtimeスコープを指定した場合、コンパイル時にのみ必要な依存関係は組み込まれません。 - ファイルが正しくコピーされない:
<includes>と<excludes>属性のパターンが正しいか確認してください。 - 実行可能なJARファイルが実行できない: マニフェストファイルに
Main-Class属性が正しく設定されているか確認してください。コンポーネント記述子を使用している場合は、設定が正しいか確認してください。 - ビルドエラー: ログを注意深く確認し、エラーメッセージに基づいて問題を特定してください。Maven Assembly PluginのドキュメントやStack Overflowなどのコミュニティフォーラムも参考になります。
7. 参考文献
- Maven Assembly Plugin公式ドキュメント: https://maven.apache.org/plugins/maven-assembly-plugin/
この詳細な説明が、Maven Assembly Pluginを理解し、活用するための一助となれば幸いです。