はじめに
初めてjavaを使って開発する機会がありビルドツールとしてMavenを採用しました。
開発環境を設定する際になんとなくで使用していたため、自分の理解のためにまとめてみました。
Mavenとは
MavenはApatche Software Foundationで開発されたソフトウェアプロジェクト管理ツールです。読み方は「メイヴェン」。Project Object Model(POM)と呼ばれるXML形式のファイル情報に基づき、プロジェクトの新規作成からコンパイル、テスト、パッケージング、配備などのプロジェクトのライフサイクルやライブラリの依存関係の管理などが行えます。理解ツールという面もあり、Mavenを利用したプロジェクトではビルドプロセスやプロジェクトの構成などがデフォルトで決まっているため、全体把握がしやすいというメリットがあります。
Mavenのアーキテクチャ
参考
Mavenを使用するとコンパイルやテストなどプロジェクトのライフサイクルの作業をコマンド一つで実行することができます。リモートリポジトリとローカルリポジトリは使用されるプラグインとライブラリが配置される場所になります。Mavenコマンド実行時に必要なプラグインやライブラリがリモートリポジトリからローカルリポジトリにダウンロードされ参照されます。
インストール
こちらからzipをインストールします。
現在(2023/11)の最新バージョンは3.9.5です。
任意の場所にzipの解凍後**\apache-maven-3.9.5\bin
をシステム環境変数Pathに追加してください。
mvn -v
を実行しバージョン情報が表示されたらOKです。
補足
MavenにはMaven Wrapperと呼ばれる、Mavenを自動ダウンロードし各操作ができるラッパーがあります。各開発者わざわざMavenをインストールする必要がなくなるので、実際のプロジェクトではMaven Wrapperを使用もありだと思います。Maven Wrapperを使用する場合は、mvnコマンドの代わりにmvnw.cmdを叩く形になります。実際に開発ではMaven Wrapperを使用していました。
プロジェクトの作成
新しくMavenのプロジェクトを立ち上げるにはArchetype Pluginを使用してテンプレートからプロジェクトを作成するのが手っ取り早いです。例えば以下のようなコマンドを実行します。
$ mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false
プラグインにはゴールと呼ばれる実行される処理がいくつか存在します。上記コマンドではarchetypeプラグインのgenerateゴールを実行しています。-Dではその処理に対するパラメータを指定でき、mavenプロジェクトで必要なgroupId
をcom.mycompany.app
、artifactId
をmy-app
に指定しています。またarchetypeにはいくつか種類が存在しており、今回はmaven-archetype-quickstart
と呼ばれるarchetypeが指定されます。archetypeはプロジェクトに合わせて選択する感じになると思います。
archetype一覧
※補足
vscodeを使用して開発を行う場合はMaven for Javaを使うとGUIベースでテンプレートを作成できます。
ディレクトリ構造
Mavenでは標準となるディレクトリ構造が決まっており、それに従うことが推奨されています。ディレクトリ構造を考える手前も減りますし、Mavenプロジェクトであれば同一のディレクトリ構造となるので他プロジェクトへの参画もしやすいというメリットもあるので、特に問題がなければ従うのが良いと思います。
例えば先ほどのコマンドでは以下のような構成でプロジェクト作成されています。
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
以下がディレクトリ構造の決まりです。
ディレクトリ | 説明 |
---|---|
src/main/java | アプリケーション・ライブラリのソースコード |
src/main/resources | アプリケーション・ライブラリのリソース |
src/main/filters | リソースに適用するフィルタ |
src/main/webapp | Webアプリケーションのソース |
src/test/java | テストのソースコード |
src/test/resources | テストのリソース |
src/test/filter | テストリソースに適用するフィルタ |
src/it | 統合テスト用 |
src/assembly | アセンブリ記述子。 配布用ファイル (zip や tar.gz など) の作成に関する情報。 |
src/site | サイトの作成に必要なファイル |
Introduction to the Standard Directory Layout
POM
pom.xmlはプロジェクトに関する情報を持つMavenにおいて核となる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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
上記のpom.xmlの構成は大まかな内容は以下になります。
パラメータ | 説明 |
---|---|
project | 最上位要素。必須。 |
modelVersion | POMのバージョン。必須。 |
groutId | プロジェクトを作成した組織またはグループの一意の識別子を指定する。依存関係解決のなど一意に認識するために使用されたりする。必須。 |
artifactId | 一次成果物の一意なベース名を指定する。パッケージングの際は{artifactId}-{version}.jarの形で生成される。必須。 |
version | バージョン情報。SNAPSHOTは開発中を意味する。必須。 |
name | プロジェクトの名前。Mavenで生成されたドキュメント内で使用される。 |
url | プロジェクトのurl。Mavenで生成されたドキュメント内で使用される。 |
properties | pom内でアクセスできる値のプレースホルダーの指定ができる。プレースホルダの文字列はpluginで決められている場合もあれば、任意で指定する事もできる。上記では用意されているmaven.compiler.target とmaven.compiler.source のプロパティに対してjavaのバージョン情報が指定されている。 |
dependencies | 依存関係を列挙する。上記ではjunit という単体テストライブラリが追加されている。 |
build | ディレクトリ構造の宣言やプラグインの管理を行う。上記では各プラグインのバージョン指定をしている。 |
pomにはSuper Pomと呼ばれるデフォルトのpomが存在します。プロジェクトのpomで値の指定がない場合は、このSuper Pomの値が継承されます。
POM Reference
Introduction to the POM
Super POM
ビルドライフサイクル
Mavenではビルドのプロセスが明確に定義されています。ユーザーはコマンドで各プロセスを実行することができます。組み込みではdefault
、clean
、site
の三つのビルドサイクルが存在します。それぞれdefault
はデプロイ処理、clean
はクリーニング処理,site
はプロジェクトのWebサイト作成の処理をします。
フェーズ
ライフサイクルはいくつかのフェーズで構成されています。例えばdefault
のライフサイクルは以下のようなフェーズがあります。
フェーズ | 説明 |
---|---|
validate | プロジェクトが正しく、必要な情報がすべて利用可能であることを検証する。 |
compile | プロジェクトのソースコードをコンパイルする。 |
test | コンパイルされたソースコードをテストする。 |
package | コンパイルされたコードを取得しJARやWARなどの配布可能な形式にパッケージ化する。 |
verify | 統合テストの結果に関するチェックを実行する。 |
install | ローカルの他のプロジェクトの依存関係として使用するために、パッケージをローカルリポジトリにインストールする。 |
deploy | ビルド環境で実行され、他の開発者やプロジェクトと共有するために最終パッケージをリモートリポジトリにコピーする。 |
実行
各フェーズを実行するには、mvn {フェーズ}
で対象のフェーズまで実行がされます。
最初の実行では必要なすべてのプラグインと依存関係をリモートリポジトリからローカルリポジトリにダウンロードするため時間がかかります。二回目以降はローカルリポジトリから参照されるようになるため実行時間が短縮されます。
以下から主に使うであろうフェーズの説明を記載します。
compile
$ mvn compile
上記コマンドでコンパイルされたクラスはデフォルトで${project.basedir}/target/classes
に配置されます。これもMavenが標準的なディレクトリ構成規約に従っています。
test
テストの実行
$ mvn test
テストを実行で使用されるsurefireプラグインは、特定の命名規則を持つファイルがテストとして識別されます。デフォルトでは以下のファイルが対象になります。
**/*Test.java
**/Test*.java
**/*TestCase.java
以下のファイルがデフォルトで除外されます。
**/Abstract*Test.java
**/Abstract*TestCase.java
テストコンパイルのみ
$ mvn test-compile
package
JARやWRAなどの成果物の生成
$ mvn package
上記コマンドでは${project.basedir}/target
にファイルが生成されます。デフォルトではJARファイルになります。上で作成したプロジェクトではmy-app-1.0-SNAPSHOT.jarというファイルが出来上がるはずです。
clean
$ mvn clean
${project.basedir}/target
を削除します。
また以下のようにcleanした後にpackage実行といった操作もできます。
$ mvn clean package
プラグイン
Mavenの処理はプラグインによって実行されています。例えばJARにパッケージングする場合は各フェーズでは以下のようなプラグインのゴールに紐づいています。pom.xmlでバージョンが指定されていなければ、最新のプラグインがダウンロードされて実行されます。
フェーズ | プラグイン:ゴール |
---|---|
process-resources | resources:resources |
compile | compiler:compile |
process-test-resources | resources:testResources |
test-compile | compiler:testCompile |
test | surefire:test |
package | jar:jar |
install | install:install |
deploy | deploy:deploy |
何のプラグインが実行されているかは、フェーズ実行時に出力されている情報からも確認できます。
利用できるプラグイン一覧は以下参照。
Available Plugins
pomになにも記載しなければデフォルトの設定で各プラグインのゴールが実行されます。プラグインごとにさまざまなパラメータが用意されてるため、それぞれ設定するにはpom.xmlのbuild/plugins
内で指定します。
以下ではcompiler pluginでターゲットとなるJDKのバージョンを指定しています。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</build>
依存関係
必要な依存関係はすべてpom.xmlに記載していく必要があります。
上で作成したプロジェクトではJUnitが依存関係に含まれています。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
ここでは依存関係ごとに、groupId
、artifactId
、version
、scope
の少なくとも4つを定義する必要があります。groupId
、artifactId
、version
は対象のプロジェクトのpom.xmlで指定されているものと同じです。scope
パラメータではプロジェクトがどのタイミング依存関係を解決するかを以下のような選択肢から指定できます。
値 | 説明 |
---|---|
compile | デフォルト値。常に必要な場合。 |
provided | コンパイルやテストでは必要だが、実行時には実行環境が提供してくれる場合。 |
runtime | コンパイル時には必要なく実行時に必要な場合。 |
test | テストのコンパイル・実行時に必要な場合。 |
system | 依存関係がシステム(実行環境のJREやJDK)から提供されるものである事を示す。 |
Introduction to the Dependency Mechanism
リポジトリ
Mavenでは依存関係はリポジトリから参照されます。
デフォルトではリモートリポジトリはMaven Central Repositoryになります。またはMaven Central Repositoryに加えて使用する独自のリモートリポジトリ(社内だけで共通で使用できるリポジトリなど)も設定することもできます。ローカルリポジトリはMavenを実行するPC上のディレクトリ(デフォルトは${user.home}/.m2/repository)でリモートリポジトリからダウンロードされたライブラリが含まれます。
Introduction to Repositories
おわりに
Maven全体の理解を深めることができました。
このあたりを知っておけばひとまずは迷うことなくmavenを使用できると思います。ライブラリやプラグインの細かい設定などは必要に応じて各々ドキュメントを見に行くのがよいでしょう。