POM解体新書
MavenはAntのように、プロジェクト毎に長々としたビルド手続きを記述する必要がなくなりました。それはなぜなのでしょうか?
ビルド手続きがプラグインで提供されているから・・・?
たしかにこの答えもまちがいではありません。
でももっと正しい答えを探すとするならば、それはPOMがあるからだと言えるでしょう。
POMとはProject Object Modelのことを指します。
MavenプロジェクトはこのPOMに基づいて標準化されています。プラグインもこのモデルの一部であって、それゆえにどのMavenプロジェクトでもMavenプラグインが利用できるのです。
POMはpom.xmlに記述しますが、ここではモデルとしてのPOMを俯瞰していきましょう。
POMの基本構造
POMをUMLを使って表すと以下のようになります。
Maven Project
Mavenプロジェクトは必ずグループIDとアーティファクトID、そしてバージョン番号を持ちます。グループIDとアーティファクトIDを組み合わせて、必ず一意に識別できるようにします。バージョン番号については「プロジェクトが依存するライブラリ」を参照してください。
Artifact:アーティファクト
Mavenプロジェクトのビルド成果物になります。たとえば、JARパッケージ、WARパッケージ、EARパッケージなどになります。1つのプロジェクトから出力されるアーティファクトは、基本的に1つになります。複数のアーティファクトを持つ例としてEJBが挙げられます。1つのソースからEJB本体のJARパッケージをビルドする他に、EJBクライアント用のスタブをまとめたJARパッケージをビルドするようなケースです。
アーティファクトはMavenの標準ディレクトリ構成にしたがって、ターゲットディレクトリに出力されます。
Source
アーティファクトをビルドするためのソースです。Javaソースコードの他に、プロパティやXMLといった設定ファイル、WARパッケージに必要なJSPファイルやHTMLファイルなども含まれます。ソースファイルはMavenの標準ディレクトリ構成にしたがって配置します。
Packaging:パッケージング
Artifactのタイプを表します。(JAR、WAR、EJB、EAR、MOJOなど)次に説明するBuild Lifecycleの振る舞いに影響します。
Build Lifecycle:ビルド・ライフサイクル
Mavenでは、1つのアーティファクトがビルドされる全工程(フェーズ)をビルド・ライフサイクルとして定義しています。ビルド・ライフサイクルは複数のフェーズ(Phase)から構成されていて、各フェーズで起動されるプラグイン(Plugin)のゴールが決められています。この各フェーズと対応するプラグイン・ゴールのマッピングは各Packagingタイプで異なります。
標準(default)のビルドライフサイクルから代表的なフェーズと、JARパッケージングの場合のフェーズにマッピングされるプラグイン・ゴール(イタリック)を列挙します。
- process-resources (resources:resources)
リソースファイル(*.propertiesなど)を、アーティファクトにパッケージングするためにターゲット・フォルダにコピーします。
- compile (compiler:compile)
ソースコードをコンパイルします。コンパイルされたファイルはターゲット・フォルダに出力されます。
- test-compile (compiler:testCompile)
単体テストプログラムをコンパイルします。
- test (surefire:test)
単体テストを実行します。
- package (jar:jar)
パッケージングします。
- install (install:install)
アーティファクトをローカルリポジトリにコピーします。
- deploy (deploy:deploy)
アーティファクトをリモートリポジトリにコピーしてリリースします。
Mavenをフェーズ名をパラメータにして起動することによって、そのフェーズまでの全フェーズの処理が実行されます。
例:
mvn packageを実行した場合
1.process-resources
2.compile
3.test-compile
4.test
5.package
の順で実行される。
ビルド・ライフサイクルとプラグイン、ゴールについては別の項で再度取り上げたいと思っています。
Dependency:ディペンデンシー
Mavenプロジェクトは依存するライブラリも、ディペンデンシーとしてモデル化しています。つまり依存ライブラリを管理する仕組み自体をMavenが持っているということです。実はディペンデンシー自体、Mavenプロジェクトのアーティファクトです。
したがってディペンデンシー自体もMavenプロジェクトと同様に、グループID、アーティファクトID、バージョンを持っています。
開発者は依存ライブラリのグループID、アーティファクトID、バージョンを指定しさえすれば、ライブラリの取得やビルドパスへの設定などの作業は、Mavenが全て自動的に行ってくれます。
依存ライブラリの仕組みについては「プロジェクトが依存するライブラリ」を管理するを参照してください。
Archetype:アーキタイプ
Mavenプロジェクトのテンプレートになります。アーキタイプを使ってMavenプロジェクトの雛型を出力することができます。
マルチ・プロジェクトのモデル
1つのプロジェクトに対して、1つのアーティファクトが対応することは先に述べました。
それではEARパッケージのように、WAR、EJB、JARといった複数のアーティファクトからなるアーティファクトをビルドするプロジェクトはどのように構成するのでしょうか。
このような場合は、WAR、EJB、JARをサブ・プロジェクトとして持つマルチ・プロジェクトを構成するようにします。
Maven1の場合、POMにマルチ・プロジェクトという考え方がないために、Multi-Projectプラグインでマルチ・プロジェクトを実現していました。この方法は後から継ぎ足したという感じがぬぐえず、使い勝手もあまりいいものではありませんでした。
対してMaven2ではPOM自体にサブプロジェクトの考え方が取り込まれています。
初めからPOMに取り込まれているので、pom.xmlに直接マルチプロジェクトを定義することができます。(「はじめの第一歩」参照)
とても自然な解といえるのではないでしょうか。