初心者必見!Maven の使い方をわかりやすく解説
Java開発者の皆さん、こんにちは!
プロジェクトを開発する上で、皆さんはどのようにコードをコンパイルし、必要なライブラリをまとめ、実行可能なファイルを作成していますか?もし手動でクラスパスを設定したり、大量のJARファイルをダウンロードして管理したりしているのであれば、それは非常に非効率的でエラーの温床となりやすい作業です。
そこで登場するのが、Maven です。
Mavenは、Javaプロジェクトのビルド、依存関係管理、プロジェクト情報の管理を自動化するための強力なツールです。現代のJava開発において、Mavenはデファクトスタンダードと言っても過言ではありません。多くの企業やオープンソースプロジェクトで採用されており、その使い方をマスターすることは、Java開発者にとって必須のスキルとなっています。
しかし、Mavenの公式ドキュメントは非常に詳細で網羅的である一方、初心者にとってはどこから手をつけて良いか分かりづらい側面もあります。特に、「POM」「依存関係」「リポジトリ」「ライフサイクル」「フェーズ」「ゴール」「プラグイン」といった独特の概念に最初は戸惑うかもしれません。
この記事は、まさにそんな「Mavenって聞いたことはあるけど、どう使うのか、何が便利なのかよく分からない…」「これからMavenを使ってみようと思っている」というJava初心者の皆さんに向けて、Mavenの使い方を基礎から丁寧に、そして分かりやすく解説することを目的としています。
約5000語というボリュームで、Mavenの基本的な概念からインストール方法、プロジェクトの作成、pom.xmlという重要な設定ファイルの読み方・書き方、よく使うコマンド、依存関係の管理方法、そしてちょっとした応用まで、Mavenを使う上で必要な知識を網羅します。
この記事を最後まで読めば、あなたは自分でMavenプロジェクトを作成し、外部ライブラリを追加し、プロジェクトをビルド・テスト・パッケージングできるようになっているはずです。さあ、一緒にMavenの世界へ飛び込みましょう!
1. Mavenとは何か?なぜ使うのか?
まずは、「Mavenとは何か?」という最も基本的な問いから始めましょう。
Mavenは、Apacheソフトウェア財団が開発している、Javaプロジェクトのビルド自動化ツールであり、プロジェクト管理ツールです。
かつて、Javaプロジェクトのビルドは、Antという別のツールが主流でした。Antは非常に柔軟で、XMLで記述されたタスクの集まりとしてビルド処理を定義できました。しかし、Antはあくまで「ビルドの手順」を記述するツールであり、「プロジェクトの構造」や「依存関係」を標準化する機能は持っていませんでした。そのため、プロジェクトごとにビルドスクリプトの書き方が異なり、新しいプロジェクトに参加するたびにそのプロジェクト独自のビルド手順を理解する必要がありました。また、必要なライブラリ(JARファイル)は手動でダウンロードし、プロジェクト内に配置したり、クラスパスを自分で設定したりする必要があり、これが非常に手間のかかる作業でした。
Mavenは、これらの問題を解決するために生まれました。Mavenは「規約による構成 (Convention over Configuration)」という考え方を重視しており、標準的なプロジェクト構造とビルドプロセスを提供します。これにより、プロジェクトごとに独自のビルド手順を事細かに記述する必要がなくなり、ほとんどの設定をデフォルトに任せることができます。
Mavenを使う主なメリットは以下の通りです。
- 依存関係管理 (Dependency Management): これがMavenの最も強力な機能の一つです。プロジェクトが必要とする外部ライブラリ(JARファイルなど)を、そのライブラリの名前、バージョンなどの簡単な情報だけで指定できます。Mavenは指定されたライブラリとそのライブラリがさらに依存しているライブラリ(推移的依存関係)を自動的にダウンロードし、プロジェクトのビルドパスに含めてくれます。これにより、手動でのJARファイルのダウンロードやクラスパス設定から解放されます。
- 標準化されたプロジェクト構造: Mavenは、ソースコードは
src/main/java、テストコードはsrc/test/java、リソースファイルはsrc/main/resourcesといった標準的なディレクトリ構造を推奨しています。この規約に従うことで、どのMavenプロジェクトも似たような構造になり、他の開発者がプロジェクトに参加しやすくなります。 - 標準化されたビルドライフサイクル: Mavenには、プロジェクトのクリーン、コンパイル、テスト、パッケージ化、インストール、デプロイといった一連のビルドプロセスがあらかじめ定義されています。開発者はこれらのプロセスを実行するためのコマンドを呼び出すだけでよく、プロジェクトごとにビルド手順を定義する必要がありません。
- プロジェクト情報の管理: Mavenは、プロジェクト名、バージョン、開発者、ライセンスなどの情報を
pom.xmlというファイルで一元管理します。この情報をもとに、プロジェクトのWebサイトを自動生成したり、レポートを出力したりすることも可能です。 - プラグインによる拡張性: Mavenのほとんどの機能はプラグインとして提供されています。コンパイル、テスト実行、JARファイル作成なども全てプラグインが行います。これにより、必要に応じて新しい機能を追加したり、既存の機能をカスタマイズしたりすることができます。
これらのメリットにより、MavenはJavaプロジェクトの開発、ビルド、デプロイのプロセスを大幅に効率化し、開発者の生産性を向上させます。
2. Mavenの基本概念
Mavenを理解する上で避けて通れない、いくつかの重要な概念があります。これらをしっかりと把握することが、Mavenを使いこなすための第一歩です。
2.1 プロジェクトオブジェクトモデル (POM)
Mavenにおいて、プロジェクトはPOM (Project Object Model) と呼ばれるモデルとして表現されます。これはプロジェクトの情報を記述したXMLファイルで、ファイル名は必ず pom.xml です。プロジェクトのルートディレクトリに配置されます。
pom.xml には、以下のようなプロジェクトに関するあらゆる情報が記述されます。
- プロジェクトの基本情報(プロジェクト名、バージョン、説明など)
- プロジェクトの依存関係(どの外部ライブラリが必要か)
- ビルド方法(どのプラグインを使ってどのようにビルドするか)
- ビルド設定(コンパイルオプション、テスト設定など)
- 開発者情報、ライセンス情報など
Mavenは、この pom.xml ファイルを読み込んで、プロジェクトのビルドや管理を行います。pom.xml はMavenプロジェクトの心臓部と言えます。
pom.xml の最も基本的な構成要素は以下の3つです。これらはプロジェクトを一意に識別するために使用されます。
- groupId: プロジェクトを作成した組織やグループを一意に識別するIDです。通常はJavaのパッケージ名の逆順のような形式で記述します(例:
com.example.mycompany)。 - artifactId: プロジェクト自身を一意に識別するIDです。プロジェクトの名前やモジュール名が入ることが多いです(例:
my-application,user-service)。 - version: プロジェクトの現在のバージョンです(例:
1.0.0,1.0.0-SNAPSHOT)。-SNAPSHOTが付いているバージョンは開発中のバージョン、付いていないバージョンはリリースされた安定版を表すことが多いです。
これら3つの要素(groupId, artifactId, version)をまとめて 座標 (Coordinate) と呼びます。Mavenでは、すべての成果物(プロジェクト自身、依存ライブラリ)をこの座標で管理します。
2.2 依存関係 (Dependencies)
依存関係とは、あなたのプロジェクトが動作するために必要とする外部ライブラリやモジュールのことです。例えば、データベースに接続するためにJDBCドライバーが必要だったり、ログ出力にLog4j2やSLF4jが必要だったり、Webアプリケーション開発にSpring Frameworkが必要だったりします。
Mavenでは、これらの依存関係を pom.xml の <dependencies> セクションに記述します。各依存関係は、そのライブラリの座標(groupId, artifactId, version)を指定することで定義されます。
xml
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-library</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope> <!-- この依存関係はテスト時のみ必要であることを示す -->
</dependency>
</dependencies>
Mavenは pom.xml を解析し、必要な依存ライブラリを自動的にダウンロードしてくれます。手動でJARファイルを管理する手間が省け、開発効率が大幅に向上します。
2.3 リポジトリ (Repositories)
Mavenは、依存関係として指定されたライブラリや、ビルドによって生成された成果物(JARファイルなど)を保管・取得する場所をリポジトリと呼びます。リポジトリにはいくつかの種類があります。
- ローカルリポジトリ (Local Repository): あなたのマシン上に存在するリポジトリです。Mavenがダウンロードした依存ライブラリや、あなたがビルドしてローカルにインストールした成果物がここに保存されます。一度ダウンロードされたライブラリはここにキャッシュされるため、次回以降は高速に利用できます。デフォルトでは、ユーザーホームディレクトリ下の
.m2/repositoryディレクトリに作成されます。 - 中央リポジトリ (Maven Central Repository): インターネット上に存在する、世界中の様々なオープンソースライブラリが登録されている大規模なリポジトリです。Mavenはデフォルトでこのリポジトリからライブラリを探しに行きます。Spring Framework, Apache Commons, JUnitなど、有名なライブラリのほとんどがここにあります。URLは
https://repo.maven.apache.org/maven2/です。 - リモートリポジトリ (Remote Repositories): 中央リポジトリ以外の、インターネット上や組織内に存在する任意のリポジトリです。組織内で開発された共通ライブラリを共有するために使用したり、中央リポジトリにはない特定のライブラリを提供するために使用したりします。
pom.xmlや設定ファイル (settings.xml) で指定することで利用できます。
Mavenは依存ライブラリが必要になった場合、まずローカルリポジトリを探します。見つかればそれを利用します。見つからなければ、中央リポジトリやその他のリモートリポジトリからダウンロードし、ローカルリポジトリに保存した上で利用します。
2.4 ビルドライフサイクル (Build Lifecycle)
Mavenのビルドプロセスは、ビルドライフサイクルという概念に基づいています。ビルドライフサイクルは、プロジェクトをビルドする際に行われる一連の手順を定義したものです。Mavenには主に以下の3つの標準ビルドライフサイクルがあります。
- default: プロジェクトのデプロイを処理するメインのライフサイクルです。コンパイル、テスト、パッケージ化、インストール、デプロイといった主要な段階(フェーズ)を含みます。
- clean: プロジェクトのビルドによって生成されたファイルをクリーンアップ(削除)するライフサイクルです。
- site: プロジェクトのドキュメントやレポートを含むサイトを生成するライフサイクルです。
開発者が最もよく利用するのは default ライフサイクルです。
2.5 フェーズ (Phases)
ビルドライフサイクルは、順番に実行される複数のフェーズで構成されています。各フェーズはビルドプロセスにおける特定の段階を表します。defaultライフサイクルの主なフェーズを、一般的な実行順序で見てみましょう。
validate: プロジェクトが正しく構成されているか検証します。compile: プロジェクトのメインのソースコード (src/main/java以下) をコンパイルします。test: コンパイル済みのソースコードに対して、ユニットテスト (src/test/java以下) を実行します。package: コンパイル済みのコードとリソースをまとめて、JARやWARといった配布可能な形式にパッケージ化します。verify: パッケージが有効で品質基準を満たしているか検証します。(例えば、統合テストを実行するなど)install: プロジェクトのパッケージを、自身のローカルリポジトリにインストールします。これにより、他のローカルプロジェクトがこのプロジェクトを依存関係として利用できるようになります。deploy: プロジェクトのパッケージを、リモートリポジトリ(共有リポジトリなど)にコピーします。これにより、他の開発者や他のシステムがこのプロジェクトを依存関係として利用できるようになります。
これらのフェーズは順番に実行されます。例えば、mvn install コマンドを実行すると、validate → compile → test → package → verify → install というように、指定したフェーズとその手前の全てのフェーズが順番に実行されます。
2.6 ゴール (Goals)
ゴールは、プラグインによって提供される特定のタスクや処理の単位です。例えば、compiler:compile というゴールはソースコードをコンパイルする処理、surefire:test というゴールはテストを実行する処理、jar:jar というゴールはJARファイルを作成する処理を表します。
Mavenのビルドライフサイクルの各フェーズには、一つ以上のゴールが関連付けられています。特定のフェーズを実行すると、そのフェーズに関連付けられたゴールが実行されます。
開発者は、mvn [フェーズ名] または mvn [プラグイン名]:[ゴール名] という形式でコマンドを実行し、ビルドプロセスを開始します。
2.7 プラグイン (Plugins)
Mavenのビルドプロセスのほとんどの実際の処理は、プラグインによって実行されます。コンパイル、テスト、パッケージング、レポート生成など、Mavenができることのほぼ全てがプラグインとして実装されています。
Mavenはコアとなるフレームワークを提供し、プラグインが具体的なタスクを実行する、という役割分担になっています。これにより、Maven自体はシンプルに保たれつつ、プラグインを追加することで様々な機能に対応できるようになっています。
プラグインは pom.xml の <build> セクションで設定できます。どのプラグインを使うか、そしてそのプラグインのどのゴールをどのフェーズで実行するか、といった設定が可能です。
xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- 他のプラグイン設定 -->
</plugins>
</build>
上記の例では、maven-compiler-plugin というプラグインを使って、コンパイル対象のJavaバージョンを1.8に設定しています。
3. Mavenのインストール
Mavenを使うためには、まず開発環境にMavenをインストールする必要があります。MavenはJavaで動作するため、事前にJava Development Kit (JDK) がインストールされている必要があります。
3.1 前提条件: Java JDKのインストール
Maven 3.9以降を使用する場合は、Java 8以上が必要です。Maven 3.8以前を使用する場合はJava 7でも動作しますが、セキュリティ上の理由や新しい機能を利用するためにも、最新のMavenとJDKの組み合わせ(例えば Maven 3.9+ と JDK 11 or 17 or 21)を推奨します。
Oracle JDK、OpenJDK、Adoptium OpenJDKなど、どのディストリビューションでも構いません。まだJDKをインストールしていない場合は、いずれかをダウンロードしてインストールしておいてください。
JDKが正しくインストールされているか確認するには、コマンドプロンプトまたはターミナルを開いて以下のコマンドを実行します。
bash
java -version
javac -version
Javaのバージョン情報が表示されればOKです。
3.2 OSごとのMavenインストール方法
Mavenは、公式サイトからバイナリファイルをダウンロードしてインストールするのが一般的です。
Maven公式サイト: https://maven.apache.org/download.cgi
このページから、最新版のバイナリファイル(apache-maven-X.Y.Z-bin.zip または apache-maven-X.Y.Z-bin.tar.gz)をダウンロードします。
ダウンロードしたファイルを、任意のディレクトリ(例えば C:\Program Files\Apache\maven や /opt/apache/maven)に展開してください。この展開されたディレクトリを MAVEN_HOME と呼びます。
Windowsでのインストール
- Maven公式サイトから
apache-maven-X.Y.Z-bin.zipをダウンロードします。 - ダウンロードしたZIPファイルを、例えば
C:\Program Files\Apache\mavenのような場所に展開します。展開後のディレクトリ構成はC:\Program Files\Apache\maven\apache-maven-X.Y.Zのようになります。このapache-maven-X.Y.Zが MAVEN_HOME です。 - 環境変数を設定します。
- 「システムのプロパティ」を開き、「詳細設定」タブの「環境変数」ボタンをクリックします。
- システム環境変数に、以下の2つの変数を追加します。
- 変数名:
MAVEN_HOME - 変数値: Mavenを展開したディレクトリのパス(例:
C:\Program Files\Apache\maven\apache-maven-X.Y.Z) - 変数名:
JAVA_HOME - 変数値: JDKをインストールしたディレクトリのパス(例:
C:\Program Files\Java\jdk-X)
- 変数名:
- システム環境変数の中から
Pathという変数を選択し、「編集」をクリックします。 - 新規に
%MAVEN_HOME%\binを追加します。既存のPathエントリとはセミコロン;で区切ってください。また、既に%JAVA_HOME%\binがPathに含まれているか確認してください。
macOSでのインストール
macOSでは、Homebrewというパッケージマネージャーを使うと簡単にインストールできます。Homebrewがインストールされていない場合は、先にHomebrewをインストールしてください。
- ターミナルを開き、以下のコマンドを実行します。
bash
brew install maven - これでMavenがインストールされます。Homebrewは自動的に環境変数を設定してくれます。
- 手動でインストールする場合:
- Maven公式サイトから
apache-maven-X.Y.Z-bin.tar.gzをダウンロードします。 - ダウンロードしたTAR.GZファイルを任意の場所に展開します。例えば
/Users/yourusername/apache-maven-X.Y.Zのような場所です。これを MAVEN_HOME とします。 - 環境変数を設定します。
.bash_profileや.zshrcといったシェル設定ファイルを開き、以下の行を追加します。
bash
export MAVEN_HOME=/Users/yourusername/apache-maven-X.Y.Z # 展開したパスに置き換えてください
export PATH=$PATH:$MAVEN_HOME/bin
# JAVA_HOMEも設定が必要です (多くの場合 ~/.bash_profile や ~/.zshrc に既に設定されているはず)
# export JAVA_HOME=/path/to/your/jdk - 設定ファイルを再読み込みします。
bash
source ~/.bash_profile # または source ~/.zshrc
- Maven公式サイトから
Linuxでのインストール
Linuxディストリビューションによっては、aptやyumなどのパッケージマネージャーでインストールできます。
- Debian/Ubuntu系:
bash
sudo apt update
sudo apt install maven - Fedora/CentOS/RHEL系:
bash
sudo yum install maven
# または
sudo dnf install maven
パッケージマネージャーを使用しない手動インストールは、macOSの手順と同様です。バイナリファイルをダウンロード・展開し、環境変数 MAVEN_HOME と PATH を設定します。.bashrc や .profile といったシェル設定ファイルに設定を記述します。
3.3 インストール確認
どのOSでも、インストールと環境変数の設定が終わったら、新しいコマンドプロンプトまたはターミナルを開き、以下のコマンドを実行してMavenが正しくインストールされたか確認します。
bash
mvn -v
Mavenのバージョン、Javaのバージョン、OSの情報などが表示されれば、インストールは成功です。
Apache Maven 3.9.4 (...)
Maven home: ...
Java version: 17.0.8, vendor: ...
Java home: ...
Default locale: ..., Platform encoding: ...
OS name: "windows 11", version: "10.0", arch: "amd64", family: "windows"
4. 基本的なMavenプロジェクトの作成
Mavenのインストールが完了したら、実際にMavenプロジェクトを作成してみましょう。Mavenには、様々な種類のプロジェクトのひな形(Archetype)が用意されており、それを利用してプロジェクトの初期構造を簡単に生成できます。
最も基本的なJavaアプリケーションのプロジェクトを作成するには、maven-archetype-quickstart というArchetypeを使用します。
4.1 mvn archetype:generate コマンド
プロジェクトを作成するには、以下のコマンドを使用します。
bash
mvn archetype:generate
このコマンドを実行すると、対話形式でプロジェクトの作成が進みます。使用するArchetype、プロジェクトの座標(groupId, artifactId, version)、パッケージ名などを順に入力していきます。
4.2 maven-archetype-quickstart を使ったプロジェクト作成例
今回は maven-archetype-quickstart を指定してプロジェクトを作成してみます。コマンドプロンプトまたはターミナルで、プロジェクトを作成したいディレクトリに移動してから実行します。
“`bash
プロジェクトを作成したいディレクトリで実行
cd /path/to/your/projects
Archetype生成コマンド実行
mvn archetype:generate
“`
コマンドを実行すると、まず使用するArchetypeの選択を求められます。大量のArchetypeが表示されますが、今回は maven-archetype-quickstart を使いたいので、archetypeArtifactId のリストから maven-archetype-quickstart に対応する番号を入力するか、maven-archetype-quickstart と直接入力します。
例:
Choose archetype:
...
31: internal -> org.apache.maven.archetypes:maven-archetype-quickstart (A simple Java project)
...
Choose a number or apply filter (format: [groupId:]artifactId, a number or empty to browse): 31 <-- 31番を入力(環境により番号は異なります)
次に、Archetypeのバージョンを選択します。通常は最新版を選択すれば良いでしょう。
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
...
2. Enter an archetype version (from preceding list): 1.4 <-- 最新版のバージョンを入力
続いて、プロジェクトの座標(groupId, artifactId, version)とパッケージ名を尋ねられます。
Define value for property 'groupId': com.example.myproject <-- プロジェクトのGroupIdを入力
Define value for property 'artifactId': my-app <-- プロジェクトのArtifactIdを入力
Define value for property 'version' 1.0-SNAPSHOT: : <-- バージョンを入力(デフォルトでよければそのままEnter)
Define value for property 'package' com.example.myproject: : com.example.myproject.app <-- パッケージ名を入力(デフォルトでよければそのままEnter)
入力が終わると、設定内容の確認が表示されます。
Confirm properties configuration:
groupId: com.example.myproject
artifactId: my-app
version: 1.0-SNAPSHOT
package: com.example.myproject.app
Y: : <-- 内容が正しければ Y を入力してEnter
Y を入力してEnterを押すと、プロジェクトのひな形が指定したディレクトリ(ここでは my-app という名前のディレクトリ)に生成されます。
4.3 生成されるプロジェクト構造
my-app ディレクトリの中に、以下のような標準的なMavenプロジェクト構造が作成されます。
my-app/
├── pom.xml <-- プロジェクトオブジェクトモデルファイル
└── src/
├── main/
│ ├── java/ <-- メインのJavaソースコードを配置するディレクトリ
│ │ └── com/
│ │ └── example/
│ │ └── myproject/
│ │ └── app/
│ │ └── App.java <-- サンプルメインクラス
│ └── resources/ <-- メインのリソースファイル(プロパティファイルなど)を配置するディレクトリ
└── test/
├── java/ <-- テストのJavaソースコードを配置するディレクトリ
│ └── com/
│ └── example/
│ └── myproject/
│ └── app/
│ └── AppTest.java <-- サンプルテストクラス (JUnit)
└── resources/ <-- テストのリソースファイルを配置するディレクトリ
src/main/java: アプリケーションの本体となるJavaソースコードを配置する場所です。src/main/resources: アプリケーションに必要なリソースファイル(設定ファイル、画像など)を配置する場所です。src/test/java: ユニットテストや結合テストのJavaソースコードを配置する場所です。src/test/resources: テストに必要なリソースファイルを配置する場所です。pom.xml: このプロジェクトのビルド設定、依存関係などが記述されたファイルです。
この構造はMavenの「規約」であり、ほとんどのMavenプロジェクトがこの構造に従っています。これにより、初めて見るMavenプロジェクトでも、どこにどのファイルがあるかすぐに理解できるようになっています。
5. pom.xml の詳細
Mavenプロジェクトの心臓部である pom.xml ファイルについて、さらに詳しく見ていきましょう。プロジェクトを作成した際に生成された my-app/pom.xml をテキストエディタで開いてみてください。内容はArchetypeのバージョンによって多少異なりますが、基本的な構造は同じです。
“`xml
<groupId>com.example.myproject</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version> <!-- バージョンは異なる場合があります -->
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
“`
主要な要素について解説します。
<project>:pom.xmlファイルのルート要素です。名前空間などの定義が含まれます。<modelVersion>: POMモデルのバージョンを指定します。現在の標準は4.0.0です。<groupId>,<artifactId>,<version>: プロジェクト自身の座標です。プロジェクト作成時に指定した値が入っています。<name>: プロジェクトの表示名です。<url>: プロジェクトのウェブサイトURLです。<properties>: POM内で共通して使用するプロパティ(変数)を定義します。ビルド設定などでバージョンやエンコーディングなどを一元管理するのに便利です。project.build.sourceEncoding: ソースファイルのエンコーディングを指定します。UTF-8が推奨です。maven.compiler.source,maven.compiler.target: コンパイル時のJavaソースバージョンとターゲット(生成されるクラスファイル)バージョンを指定します。
<dependencies>: プロジェクトが依存する外部ライブラリを定義します。一つ以上の<dependency>要素を含みます。<dependency>: 個々の依存ライブラリを定義します。必須要素は<groupId>,<artifactId>,<version>です。<groupId>,<artifactId>,<version>: 依存するライブラリの座標です。<scope>: その依存関係がどのフェーズで必要かを示します。重要な概念なので後述します。
<build>: プロジェクトのビルドに関する設定を記述します。ビルドディレクトリ、最終成果物の名前、使用するプラグインなどを指定できます。<plugins>: ビルドプロセスで使用するプラグインを定義します。一つ以上の<plugin>要素を含みます。<plugin>: 使用するプラグインを定義します。必須要素は<groupId>,<artifactId>,<version>です(<version>は省略可能ですが、ビルドの再現性のために明示的に指定するのが推奨です)。<configuration>: プラグイン固有の設定を記述します。上記の例では、maven-compiler-pluginに対してコンパイルオプションを指定しています。
5.1 依存関係の <scope>
依存関係の <scope> 要素は、その依存ライブラリがビルドのどの段階(フェーズ)で必要になるかを定義します。これにより、必要なライブラリだけがクラスパスに含まれるようになり、最終的な成果物のサイズを最適化したり、依存関係の衝突を防いだりできます。主要なスコープは以下の通りです。
compile(デフォルト): 最も一般的なスコープです。依存ライブラリは、コンパイル時、テスト時、実行時の全てでクラスパスに含まれます。プロジェクトをパッケージ化する際に、一緒に含められます。(例: ほとんどの外部ライブラリ、Spring Frameworkなど)test: 依存ライブラリはテストのコンパイル時とテスト実行時のみクラスパスに含まれます。メインのコードのコンパイルや実行時には含まれません。プロジェクトをパッケージ化する際にも含まれません。(例: JUnit, Mockitoなどのテストライブラリ)provided: 依存ライブラリはコンパイル時とテスト時のみクラスパスに含まれます。実行時には含まれません。実行環境(例えばServletコンテナやアプリケーションサーバー)によって提供されることが期待されるライブラリに使用します。(例: Servlet API)runtime: 依存ライブラリはテスト時と実行時のみクラスパスに含まれます。コンパイル時には含まれません。コンパイルは不要だが実行時には必要なライブラリに使用します。(例: JDBCドライバー)system: 依存ライブラリは、システムパスから提供されます。<systemPath>要素でJARファイルの場所を明示的に指定する必要があります。ローカルの特定のJARファイルを参照したい場合に使用できますが、Mavenのリポジトリシステムから外れるため、非推奨です。特別な理由がない限り使用すべきではありません。import:<dependencyManagement>セクション内でのみ有効なスコープです。他のPOM(通常は親POMやBOM – Bill Of Materials)で定義された依存関係のリストをインポートし、このPOMの<dependencyManagement>にマージするために使用します。これにより、複数のPOM間で依存関係のバージョンを一元管理できます。
test スコープの依存関係は、アプリケーションの実行時には含まれないため、例えば mvn package で作成されるJARファイルには含まれません。これは非常に重要です。
5.2 その他の重要なPOM要素(概要)
<parent>: このPOMが継承する親POMを指定します。共通の設定(依存関係のバージョン、プラグインの設定など)を親POMに集約し、子POMでそれを継承することで、複数のプロジェクトやモジュール間で設定を共有・一元管理できます。特にマルチモジュールプロジェクトで重要になります。<dependencyManagement>: 依存関係のバージョンを管理するためのセクションです。ここに記述された依存関係は、それ自体では依存関係として追加されませんが、<dependencies>セクションで同じ groupId と artifactId を持つ依存関係を定義する際に、バージョン指定を省略できるようになります。バージョンの一元管理に役立ちます。<pluginManagement>:<dependencyManagement>のプラグイン版です。使用するプラグインのバージョンやデフォルト設定を定義しておき、<build>セクションでプラグインを定義する際にバージョン指定を省略できるようにします。<profiles>: 特定の環境や目的に応じてビルド設定を切り替えるための機能です。例えば、開発環境用と本番環境用で異なる設定ファイルを含めたり、特定のプロファイルがアクティブな時だけ実行されるテストを定義したりできます。-P [プロファイルID]オプションでアクティベートできます。
これらの要素を使いこなすことで、より複雑なプロジェクト構成や高度なビルド設定が可能になります。
6. Mavenコマンドラインの使い方
Mavenの操作は、主にコマンドラインから行います。ここでは、よく使うMavenコマンドとその役割、ライフサイクルフェーズの実行方法などを解説します。
基本的なコマンドの書式は以下の通りです。
bash
mvn [options] [<goals> | <phases>]
例えば、プロジェクトをクリーンして、コンパイルし、テストを実行し、パッケージ化して、ローカルリポジトリにインストールする場合、defaultライフサイクルの install フェーズを指定します。
bash
cd my-app # プロジェクトのルートディレクトリに移動
mvn install
このコマンドを実行すると、Mavenは my-app ディレクトリの pom.xml を読み込み、defaultライフサイクルの install フェーズを実行します。前述の通り、install フェーズは validate, compile, test, package, verify フェーズを順番に実行した後に実行されます。
6.1 主なコマンドとその役割
よく使うMavenコマンド(実際にはライフサイクルフェーズまたはゴール)をいくつか見てみましょう。これらのコマンドは、プロジェクトのルートディレクトリ(pom.xml がある場所)で実行します。
mvn clean: cleanライフサイクルのcleanフェーズを実行します。これにより、前回のビルドで生成されたファイル(targetディレクトリ以下など)が削除され、クリーンな状態でビルドを開始できます。
bash
mvn cleanmvn compile: defaultライフサイクルのcompileフェーズを実行します。src/main/javaディレクトリ以下のJavaソースコードをコンパイルし、target/classesディレクトリにクラスファイルを生成します。validateフェーズも実行されます。
bash
mvn compilemvn test: defaultライフサイクルのtestフェーズを実行します。src/test/javaディレクトリ以下のテストコードをコンパイルし、テストを実行します。validate,compileフェーズも実行されます。テスト結果はtarget/surefire-reportsディレクトリに生成されます。
bash
mvn testmvn package: defaultライフサイクルのpackageフェーズを実行します。コンパイル済みコードとリソースをまとめて、JAR(Javaアプリケーションの場合)やWAR(Webアプリケーションの場合)といった配布可能な形式にパッケージ化します。成果物はtargetディレクトリに生成されます。validate,compile,testフェーズも実行されます。
bash
mvn packagemvn install: defaultライフサイクルのinstallフェーズを実行します。packageフェーズまで実行した後、生成された成果物(JAR/WARなど)をローカルリポジトリにインストールします。validate,compile,test,package,verifyフェーズも実行されます。ローカルにインストールすることで、他のローカルプロジェクトからこの成果物を依存関係として参照できるようになります。
bash
mvn installmvn deploy: defaultライフサイクルのdeployフェーズを実行します。installフェーズまで実行した後、生成された成果物をリモートリポジトリ(組織内の共有リポジトリなど)にデプロイします。これにより、他の開発者やCI/CDサーバーなどがこの成果物を利用できるようになります。リモートリポジトリの設定が必要です。
bash
mvn deploymvn verify: defaultライフサイクルのverifyフェーズを実行します。packageフェーズまで実行した後、パッケージの検証を行います(例えば、統合テストなど)。
bash
mvn verify
これらのライフサイクルフェーズコマンドは、指定したフェーズとその前の全てのフェーズを実行するということを覚えておきましょう。例えば mvn package は validate → compile → test → package の順に実行します。
6.2 複数のフェーズ/ゴールを実行する
複数のフェーズやゴールを一度のコマンドで実行することも可能です。スペースで区切って指定します。
“`bash
クリーンしてからパッケージ化し、ローカルインストール
mvn clean install
コンパイルのみ実行
mvn compile
compiler プラグインの compile ゴールのみ実行
mvn compiler:compile
“`
mvn clean install は非常によく使われるコマンドパターンです。これにより、前回のビルドの成果物を削除してから、コンパイル、テスト、パッケージ、ローカルインストールまで一連の処理を実行できます。
特定のプラグインの特定のゴールのみを実行したい場合は、[プラグインのprefix]:[ゴール名] の形式で指定します。プラグインのprefixは通常 artifactId から maven- や -plugin を除いたものです(例: maven-compiler-plugin は compiler)。
6.3 よく使うオプション
Mavenコマンドには様々なオプションを指定できます。いくつかよく使うオプションを紹介します。
-
-D<propertyName>=<propertyValue>: POMの<properties>で定義されたプロパティや、プラグインの設定値をコマンドラインから上書きします。
“`bash
# Javaバージョンを一時的に変更してコンパイル
mvn compile -Dmaven.compiler.source=11 -Dmaven.compiler.target=11テスト実行時に特定のシステムプロパティを設定
mvn test -Dmy.test.env=production
* **`-P <profileId>`**: 指定したプロファイルをアクティベートしてビルドを実行します。複数のプロファイルを指定する場合はカンマで区切ります (`-P dev,integration-test`)。bash‘release’ プロファイルをアクティベートしてデプロイ
mvn deploy -P release
* **`-U` (--update-snapshots)**: リモートリポジトリから最新のSNAPSHOTバージョンを取得します。通常MavenはSNAPSHOTバージョンを一定期間キャッシュしますが、このオプションを指定すると強制的に更新チェックを行います。bashSNAPSHOT依存関係の最新版を取得してビルド
mvn clean install -U
* **`-o` (--offline)**: オフラインモードでビルドを実行します。リモートリポジトリへの接続を試みず、ローカルリポジトリにあるものだけでビルドしようとします。インターネット接続がない場合や、依存関係が全てローカルにあることがわかっている場合に高速化できます。bashオフラインでパッケージ化
mvn package -o
* **`-N` (--non-recursive)**: マルチモジュールプロジェクトのルートディレクトリで実行した場合に、子モジュールをビルドせず、ルートモジュール(親POM)のみを処理します。bash親POMのインストールのみ実行 (子モジュールはビルドしない)
mvn install -N
* **`-X` (--debug)**: デバッグモードで実行し、非常に詳細なログを出力します。ビルドがうまくいかない場合に問題の原因を特定するのに役立ちます。bashデバッグ情報を出力しながらビルド
mvn clean install -X
``-e
* **(--errors)**: ビルドエラーが発生した場合に、より詳細なエラーレポートを出力します。-X` よりは出力が少ないですが、エラーの原因特定に役立ちます。
これらのオプションを組み合わせることで、より細かくビルドプロセスを制御できます。
7. 依存関係の詳細な管理
Mavenの強力な機能である依存関係管理について、もう少し掘り下げて解説します。
7.1 推移的依存関係 (Transitive Dependencies)
Mavenの依存関係管理における非常に便利な機能の一つが、推移的依存関係です。
あなたがプロジェクトでライブラリAを依存関係として追加したとします。ところが、ライブラリA自体が動作するために、ライブラリBとCに依存している場合があります。Mavenは、あなたがライブラリAを依存関係として追加するだけで、ライブラリAが依存しているライブラリBとCも自動的にダウンロードして、プロジェクトのクラスパスに含めてくれます。これが推移的依存関係です。
これにより、開発者は直接必要なライブラリだけを意識すればよく、そのライブラリがさらに依存しているライブラリを芋づる式に手動で探し出して追加する手間が省けます。
7.2 依存関係ツリーの確認
プロジェクトにどのような依存関係が、推移的に含まれているのかを確認したい場合があります。特に、依存関係の競合が発生した際に、どのパスでそのライブラリが追加されているかを知ることは重要です。
これを確認するには、dependency:tree ゴールを使用します。
bash
mvn dependency:tree
このコマンドを実行すると、プロジェクトの依存関係がツリー構造で一覧表示されます。
[INFO] com.example.myproject:my-app:jar:1.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.11:test <-- 直接の依存関係
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test <-- junit 4.11 が依存している推移的依存関係
[INFO] \- org.apache.logging.log4j:log4j-core:jar:2.20.0:compile <-- 追加した依存関係の例
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.20.0:compile <-- log4j-core が依存している推移的依存関係
[INFO] \- org.apache.logging.log4j:log4j-slf4j2-impl:jar:2.20.0:compile <-- log4j-core が依存している推移的依存関係
[INFO] \- org.slf4j:slf4j-api:jar:2.0.7:compile <-- log4j-slf4j2-impl が依存している推移的依存関係
このツリーを見ることで、どのライブラリがどのスコープで、そしてどのライブラリを介してプロジェクトに取り込まれているかを把握できます。
7.3 依存関係の競合とその解決策
推移的依存関係は非常に便利ですが、問題を引き起こすこともあります。最も一般的な問題は依存関係の競合 (Dependency Conflict) です。
これは、同じartifactIdを持つライブラリが、異なるバージョンで複数のパスからプロジェクトに取り込まれる場合に発生します。例えば、ライブラリAが library-x:1.0 に依存しており、ライブラリBが library-x:2.0 に依存している状態で、あなたのプロジェクトがライブラリAとライブラリBの両方に依存している場合です。Mavenはどちらのバージョンの library-x を採用すべきか判断する必要があります。
Mavenのデフォルトの競合解決ルールはシンプルです。依存関係ツリーで、あなたのプロジェクトのPOMからより近い位置にある方のバージョンが採用されます。 同じ距離にある場合は、pom.xml に最初に記述されている方が採用されます。
しかし、この自動解決が常にうまくいくとは限りません。採用されたバージョンが、それを必要とするライブラリにとって互換性のないバージョンだった場合、実行時にエラーが発生する可能性があります。
この問題を解決するには、以下の方法があります。
<exclusions>を使用する: 依存関係を追加する際に、特定の推移的依存関係を除外します。例えば、ライブラリAがlibrary-xの古いバージョンに依存しているが、プロジェクト全体で新しいバージョンを使いたい場合、ライブラリAの依存関係定義からlibrary-xを除外します。
xml
<dependency>
<groupId>com.example</groupId>
<artifactId>library-A</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.example</groupId>
<artifactId>library-x</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>library-x</artifactId>
<version>2.0.0</version> <!-- 明示的に新しいバージョンを追加 -->
</dependency>
これで、ライブラリAを介して取り込まれるlibrary-xは除外され、代わりにあなたが明示的に指定した2.0.0が使用されます。-
<dependencyManagement>を使用する: 親POMやルートPOMの<dependencyManagement>セクションで、競合しているライブラリの望ましいバージョンを定義します。
“`xml
com.example
library-x
2.0.0
com.example
library-A
1.0.0
com.example
library-B
1.0.0
com.example
library-x
``でバージョンを指定しておくと、セクションで同じ座標を持つ依存関係が登場した際に、そちらでバージョンが指定されていなければ` のバージョンが優先されます。これは、複数のモジュールやプロジェクトで同じライブラリのバージョンを統一したい場合に非常に有効な方法です。
依存関係の競合は、ビルド時ではなく実行時に NoClassDefFoundError や NoSuchMethodError といった形で現れることが多いため、原因特定が難しい場合があります。mvn dependency:tree を活用して依存関係の状況を把握することが、解決への第一歩となります。
7.4 バージョンの指定方法
依存関係のバージョンは、通常は具体的なバージョン(例: 1.2.0)を指定しますが、特別なバージョン指定方法もあります。
- 固定バージョン:
1.2.0のように具体的なバージョンを指定します。最も推奨される方法です。ビルドの再現性が保証されます。 - SNAPSHOTバージョン:
1.2.0-SNAPSHOTのように-SNAPSHOTが付いたバージョンです。これは開発中のバージョンを意味します。Mavenは通常、SNAPSHOTバージョンの依存関係をビルド時にリモートリポジトリから定期的にチェックし、最新版があればダウンロードします。これにより、共同開発している他のモジュールなどの最新の開発版を容易に利用できます。ただし、ビルドごとに異なるSNAPSHOTバージョンが取り込まれる可能性があるため、ビルドの再現性は保証されません。 - バージョン範囲指定: バージョンを
[1.0, 2.0)のように範囲で指定できます。これは「1.0以上2.0未満」という意味です。開発時には便利ですが、どのバージョンが実際に使われるかが不確定になるため、プロダクションビルドでは推奨されません。
通常は固定バージョンを使用し、開発中の依存関係にはSNAPSHOTを使用するのがベストプラクティスです。
8. プラグインの詳細な使い方
Mavenのビルドプロセスを担うプラグインについて、より具体的な使い方を見ていきましょう。プラグインは pom.xml の <build> セクションの <plugins> リストに追加することで使用します。
xml
<build>
<plugins>
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<executions> <!-- オプション:特定のフェーズでゴールを実行する場合などの設定 -->
...
</executions>
<configuration> <!-- オプション:プラグイン固有の設定 -->
...
</configuration>
<dependencies> <!-- オプション:プラグイン自身が依存するライブラリ -->
...
</dependencies>
</plugin>
<!-- 他のプラグイン -->
</plugins>
</build>
<plugin> 要素の中では、プラグインの座標(groupId, artifactId, version)を指定します。<configuration> 要素で、プラグイン固有のパラメータを設定できます。
8.1 よく使う主要プラグイン
Mavenには標準的な処理を行うための多くのプラグインが用意されています。これらは通常 org.apache.maven.plugins または org.codehaus.mojo というgroupIdを持っています。
maven-compiler-plugin: Javaソースコードをコンパイルします。- 主な設定:
<source>,<target>(Javaバージョン),<encoding>,<compilerArgs>(javacオプション) など。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
このプラグインは default ライフサイクルのcompileおよびtest-compileフェーズに、自動的にcompiler:compileおよびcompiler:testCompileゴールがバインドされています。明示的に<plugin>セクションに記述するのは、バージョンを指定したりデフォルト設定を変更したりする場合です。
- 主な設定:
maven-surefire-plugin: ユニットテストを実行します。デフォルトではsrc/test/javaディレクトリ以下の*Test.java,*Tests.java,*TestCase.javaという命名規約に従うクラスを探して実行します。- 主な設定:
<includes>,<excludes>(実行するテストクラスのパターン),<skipTests>(テストをスキップするかどうか),<argLine>(JVMオプション) など。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<!-- 例: 特定のテストのみ実行 -->
<includes>
<include>**/MySpecificTest.java</include>
</includes>
<!-- 例: パフォーマンステストをスキップ -->
<excludes>
<exclude>**/Performance*Test.java</exclude>
</excludes>
<!-- 例: テスト実行時のJVMオプション -->
<argLine>-Dfile.encoding=${project.build.sourceEncoding}</argLine>
<!-- 例: テストをスキップする場合 -->
<!-- <skipTests>true</skipTests> -->
</configuration>
</plugin>
このプラグインも default ライフサイクルのtestフェーズに自動的にバインドされています。
- 主な設定:
maven-jar-plugin: JARファイルを作成します。- 主な設定:
<archive>(MANIFEST.MF の設定),<finalName>(出力されるJARファイル名) など。実行可能なJARを作成する場合に<archive>内で<manifest><mainClass>...</mainClass></manifest>を設定します。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.example.myproject.app.App</mainClass> <!-- 実行したいメインクラス -->
</manifest>
</archive>
</configuration>
</plugin>
このプラグインは default ライフサイクルのpackageフェーズに自動的にバインドされています。
- 主な設定:
maven-war-plugin: WARファイルを作成します。(Webアプリケーションプロジェクトの場合)maven-install-plugin: 成果物をローカルリポジトリにインストールします。maven-deploy-plugin: 成果物をリモートリポジトリにデプロイします。maven-source-plugin: ソースコードを含むJARファイルを作成します。maven-javadoc-plugin: Javadocを含むJARファイルを作成します。exec-maven-plugin(groupId:org.codehaus.mojo): Javaクラスや外部プログラムを実行します。アプリケーションのエントリポイントをビルドプロセスの一部として実行したり、CLIツールを実行したりするのに便利です。
xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.myproject.app.App</mainClass>
<arguments>
<argument>arg1</argument>
<argument>arg2</argument>
</arguments>
</configuration>
</plugin>
このプラグインを使用すると、mvn exec:javaコマンドなどでmainClassに指定したクラスを実行できます。
8.2 プラグインのゴールを特定のフェーズにバインドする
ほとんどの標準的なプラグインは、そのゴールがデフォルトで特定のライフサイクルフェーズにバインドされています(例: compiler:compile は compile フェーズ)。しかし、独自のゴールを特定のフェーズで実行したい場合や、既存のゴールを別のフェーズで実行したい場合は、<executions> セクションを使用します。
xml
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<executions>
<execution>
<id>my-execution-id</id> <!-- 実行を識別するID -->
<phase>generate-resources</phase> <!-- ゴールを実行したいフェーズ -->
<goals>
<goal>my-custom-goal</goal> <!-- 実行したいゴール -->
<goal>another-goal</goal>
</goals>
<configuration> <!-- この実行に特化した設定 -->
...
</configuration>
</execution>
<!-- 複数の execution を定義可能 -->
</executions>
</plugin>
上記の例では、指定したプラグインの my-custom-goal および another-goal を、defaultライフサイクルの generate-resources フェーズで実行するように設定しています。
8.3 カスタムプラグインの作成(概要)
Mavenは独自のプラグインを作成することも可能です。これは、プロジェクト固有のビルドタスクや、Mavenの標準機能ではカバーできない特殊な処理を自動化したい場合に有用です。MavenプラグインはJavaで記述され、Maven APIを使用してPOM情報へのアクセスや他のMaven機能の呼び出しを行います。プラグイン開発はやや高度なトピックのため、ここでは概要に留めます。興味があれば公式ドキュメントを参照してください。
9. Mavenプロジェクトの実践
ここまで学んだ概念とコマンドを使って、簡単な実践的な作業を行ってみましょう。
9.1 外部ライブラリの追加
Log4j2というログ出力ライブラリをプロジェクトに追加してみます。Log4j2は、log4j-core と log4j-api の2つの主要なコンポーネントから成り立っています。また、SLF4jなどの他のロギングAPIと連携するためのアダプター (log4j-slf4j2-impl) もよく使用します。
my-appディレクトリのpom.xmlを開きます。-
<dependencies>セクションに、Log4j2の依存関係を追加します。バージョンはMaven Central Repositoryなどで最新版を確認してください。(例: 2.20.0)
“`xml
junit
junit
4.11
test
<!-- Log4j2 依存関係の追加 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.20.0</version> </dependency> <!-- 必要に応じて SLF4j2 impl --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j2-impl</artifactId> <version>2.20.0</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>2.0.7</version> <!-- log4j-slf4j2-impl に合わせる --> </dependency>
3. `pom.xml` を保存します。bash
4. コマンドラインでプロジェクトルートに移動し、Mavenコマンドを実行します。例えば `mvn compile` や `mvn install` を実行すると、Mavenは `<dependencies>` を読み込み、Log4j2およびその推移的依存関係を中央リポジトリからダウンロードして、ローカルリポジトリに保存します。
mvn clean install
“`
出力に “Downloading from central: …” といったログが表示され、ライブラリがダウンロードされていることが確認できます。
9.2 テストコードの書き方と実行
プロジェクト作成時にArchetypeによって簡単なテストクラス (AppTest.java) が生成されています。これを開いてみましょう。JUnit 4またはJUnit 5を使ったテストコードが書かれているはずです。
例 (JUnit 4):
“`java
package com.example.myproject.app;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
/
* Unit test for simple App.
*/
public class AppTest
{
/
* Rigorous Test 🙂
*/
@Test
public void shouldAnswerWithTrue()
{
assertTrue(true);
}
}
“`
テストコードは src/test/java 以下に配置します。通常はテスト対象のクラスと同じパッケージ構造で作成します。
テストを実行するには、mvn test コマンドを使用します。
bash
mvn test
このコマンドは、コンパイル後に maven-surefire-plugin を起動し、規約に従うテストクラス (*Test.java など) を探して実行します。テストが成功すると BUILD SUCCESS と表示され、テスト結果の概要が表示されます。テストが失敗すると BUILD FAILURE となり、失敗したテストの詳細が出力されます。テストレポートは target/surefire-reports ディレクトリに生成されます。
9.3 実行可能なJARファイルの作成
アプリケーションとして配布可能なJARファイルを作成したい場合があります。これには、作成されるJARファイルの中に依存するライブラリも含めるか、クラスパス情報を埋め込む必要があります。
一般的な方法はいくつかありますが、ここでは maven-jar-plugin を使ってクラスパス情報を含むJARを作成し、依存ライブラリを別途配置する方法と、依存ライブラリを全て含んだ「単一の実行可能JAR」(いわゆるUber JARやFat JAR)を作成する方法を紹介します。
クラスパス情報を含むJARの作成
上記 8.1 の maven-jar-plugin の設定例のように、pom.xml の <build> セクションに maven-jar-plugin を追加し、<configuration> で mainClass とクラスパスの設定を行います。
設定後、mvn package コマンドを実行します。
bash
mvn package
target ディレクトリに my-app-1.0-SNAPSHOT.jar のようなJARファイルが生成されます。このJARファイル単体では実行できません。依存ライブラリは別途、実行時のクラスパスに含める必要があります。Mavenの package フェーズは、デフォルトでは依存ライブラリを target/classes や target/test-classes にコピーしますが、最終的なJARには含めません。
依存ライブラリを別途まとめるには、maven-dependency-plugin などのプラグインを使用します。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory> <!-- lib ディレクトリにコピー -->
</configuration>
</execution>
</executions>
</plugin>
この設定を追加して mvn package を実行すると、target/lib ディレクトリに依存ライブラリのJARファイル群がコピーされます。実行時には、生成されたJARと lib ディレクトリ内のJAR全てをクラスパスに含める必要があります。
“`bash
target ディレクトリに移動してから実行
cd target
java -cp my-app-1.0-SNAPSHOT.jar;lib/ com.example.myproject.app.App # Windows の場合
java -cp my-app-1.0-SNAPSHOT.jar:lib/ com.example.myproject.app.App # macOS/Linux の場合
“`
依存ライブラリを全て含んだ単一実行可能JARの作成
依存ライブラリを全て含んだ単一のJARファイルを作成すれば、配布が容易になります。これには maven-assembly-plugin や maven-shade-plugin といったプラグインを使用します。
maven-assembly-plugin: プロジェクトの成果物や依存関係をまとめてZIPやtar.gz、あるいは単一のJARファイルなどにパッケージングするための多機能なプラグインです。maven-shade-plugin: 依存ライブラリをJARファイル内に含め、必要に応じてクラスのリネームや統合を行うことに特化したプラグインです。依存関係の競合解決機能も持ちます。実行可能JAR作成はこちらの方が適していることが多いです。
maven-shade-plugin を使用する例です。
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<!-- メインクラスを指定 -->
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.myproject.app.App</mainClass>
</transformer>
</transformers>
<!-- 出力ファイル名の設定 (任意) -->
<finalName>${project.artifactId}-executable-${project.version}</finalName>
</configuration>
</execution>
</executions>
</plugin>
この設定を追加して mvn package を実行すると、target ディレクトリに my-app-executable-1.0-SNAPSHOT.jar のような名前で依存ライブラリを全て含んだJARファイルが生成されます。このJARファイルは java -jar [ファイル名].jar コマンドで直接実行可能です。
bash
cd target
java -jar my-app-executable-1.0-SNAPSHOT.jar
10. 主要な概念の応用(概要)
より実際の開発に近い状況でMavenを使う際に知っておくと便利な概念をいくつか紹介します。
10.1 マルチモジュールプロジェクト
大規模なアプリケーションは、複数の小さなモジュールに分割して開発されることが多いです。例えば、ビジネスロジック、データアクセス、Webインターフェースなどを別々のモジュールとする構成です。Mavenはこのようなマルチモジュールプロジェクトをサポートしています。
マルチモジュールプロジェクトでは、一つ以上の子モジュールを持つ親モジュール(親POM)を作成します。親POMは <packaging>pom</packaging> と設定され、子モジュールのリストを <modules> セクションに持ちます。子モジュールはそれぞれ独自の pom.xml を持ち、<parent> 要素で親POMを指定して設定を継承します。
“`xml
<modules>
<module>core</module>
<module>web</module>
</modules>
<properties>
<java.version>11</java.version>
<spring.version>5.3.22</spring.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 子モジュール全体でバージョンを統一したい依存関係 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- ... 他の依存関係 ... -->
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<!-- 子モジュール全体でバージョンや設定を統一したいプラグイン -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<!-- ... 他のプラグイン ... -->
</plugins>
</pluginManagement>
</build>
“`
“`xml
<artifactId>core</artifactId>
<packaging>jar</packaging> <!-- このモジュールはJARを生成することを示す -->
<dependencies>
<!-- parent の dependencyManagement からバージョンを引き継ぐ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<!-- version は不要 -->
</dependency>
<!-- core モジュール固有の依存関係 -->
</dependencies>
“`
親POMのあるディレクトリで mvn install を実行すると、Mavenは自動的に <modules> に定義された子モジュールを適切な順番(依存関係のあるモジュールを先に)でビルドしていきます。
10.2 スナップショットバージョンとリリースバージョン
Mavenのバージョンには、大きく分けてSNAPSHOTバージョンとリリースバージョンがあります。
- SNAPSHOTバージョン (
1.0-SNAPSHOTなど): 現在開発中のバージョンを示します。MavenはリモートリポジトリからSNAPSHOTバージョンを取得する際に、常に最新のものを確認しにいきます。これにより、開発中の他のモジュールやライブラリの最新コードを簡単に利用できます。 - リリースバージョン (
1.0.0など): リリースされた安定版を示します。一度リリースされたバージョンは変更されません。Mavenはリリースバージョンの成果物がローカルリポジトリにあれば、リモートリポジトリには確認しにいきません。これにより、ビルドの再現性が保証されます。
開発中はSNAPSHOTバージョンを使用し、リリース時にはSNAPSHOTサフィックスを取り除いたリリースバージョンに更新するのが一般的な開発ワークフローです。Maven Release Pluginを使うことで、このリリースプロセスを自動化できます。
10.3 Mavenプロファイルを使った環境ごとのビルド
前述した <profiles> 要素を使うと、特定の環境(開発、テスト、本番など)や目的に応じてビルドの設定を切り替えることができます。
settings.xml ファイルや pom.xml ファイルでプロファイルを定義できます。プロファイルは <id> で識別され、特定のプロファイルがアクティベートされた場合にのみ有効になる <properties>, <dependencies>, <build> などの設定を含みます。
プロファイルをアクティベートする方法はいくつかあります。
- コマンドラインオプション:
mvn -P [プロファイルID] - 環境変数:
mvn -D maven.profile=[プロファイルID] - JDKバージョンなどの環境に応じた自動アクティベート:
pom.xmlの<activation>セクションで設定 - settings.xml での永続的なアクティベート:
<activeProfiles>セクションで設定
これにより、例えば本番環境用のビルド時には、テスト用の依存関係を除外したり、特定の最適化処理を行うプラグインを実行したりといったことが可能になります。
11. トラブルシューティング
Mavenを使っていると、様々なエラーに遭遇することがあります。ここでは、初心者がよく遭遇するエラーとその原因、一般的な対処法を紹介します。
11.1 “Could not find artifact…” (依存関係が見つからない)
これは非常によくあるエラーです。Mavenが必要な依存ライブラリをローカルリポジトリ、中央リポジトリ、その他の設定されたリモートリポジトリのどこからも見つけられなかった場合に発生します。
原因:
pom.xmlの依存関係の座標(groupId, artifactId, version)が間違っている。- 指定したバージョンのライブラリが、設定されているどのリポジトリにも存在しない。
- ローカルリポジトリのファイルが破損している。
- インターネットに接続できない、またはプロキシ設定が間違っているなどで、リモートリポジトリにアクセスできない。
- 組織内のプライベートリポジトリに必要なライブラリがあるのに、そのリポジトリが設定されていない。
- SNAPSHOTバージョンを指定しているが、リモートリポジトリから最新版を取得できていない。
対処法:
pom.xmlの依存関係の座標を再確認します。ライブラリの公式ドキュメントやMaven Central Repository (https://search.maven.org/) で正しい座標とバージョンを調べてください。-Uオプションを付けてコマンドを再実行します (mvn clean install -U)。これにより、SNAPSHOT依存関係の最新版が強制的に確認されます。- ローカルリポジトリが破損している可能性を考慮し、問題のライブラリが含まれるディレクトリ(
~/.m2/repository/[groupId]/[artifactId])を削除して、再度ビルドを実行してみてください。 - インターネット接続を確認します。企業のファイアウォール内にいる場合は、Mavenがリモートリポジトリにアクセスするためのプロキシ設定が必要かもしれません。設定は
settings.xmlファイルで行います。 - 必要なリモートリポジトリが
pom.xmlまたはsettings.xmlに正しく設定されているか確認します。 mvn dependency:treeコマンドで、どの依存関係を解決しようとして失敗しているかを確認します。
11.2 コンパイルエラー
Javaソースコードのコンパイルに失敗した場合に発生します。これはMaven固有の問題というよりは、コード自身の問題であることがほとんどです。
原因:
- Javaコードのシンタックスエラー。
- 必要なクラスが見つからない (
symbol not found)。これは、依存関係が正しく追加されていないか、依存関係のスコープがcompileでない場合に発生しやすいです。 - JavaバージョンがPOMの設定 (
maven.compiler.source,maven.compiler.target) と合っていない。
対処法:
- コンパイルエラーメッセージを注意深く読み、エラーが発生しているファイルと行番号を確認します。
- エラーメッセージが「symbol not found」を示している場合、そのクラスを含むライブラリが依存関係として
compileスコープで追加されているか確認します。mvn dependency:treeで確認するのも有効です。 pom.xmlのmaven-compiler-plugin設定で、使用しているJDKのバージョンとsource/targetの設定が合っているか確認します。- IDEを使用している場合は、IDE上でのコンパイルエラーも確認し、IDEのMaven設定(Javaバージョンなど)が正しいか確認します。
11.3 テスト失敗
mvn test または mvn package / mvn install 実行時にテストが失敗した場合に発生します。
原因:
- テストコード自体のバグ。
- テスト対象のアプリケーションコードのバグ。
- テスト実行環境の問題(データベース接続できない、リソースファイルが見つからないなど)。
- 依存関係の競合により、テストで使用されるライブラリのバージョンがおかしくなっている。
対処法:
- テスト失敗時の出力や、生成されたテストレポート (
target/surefire-reportsディレクトリ以下) を確認し、どのテストが失敗したか、どのような例外が発生したかを確認します。 - IDE上で単体テストを実行し、デバッグするなどして原因を特定します。
- テストの依存関係(JUnit, Mockitoなど)が
testスコープで正しく追加されているか確認します。 mvn test -Xオプションでデバッグログを出力し、テスト実行時のクラスパスなどを確認します。- 特定のテストだけを一時的に実行したい場合は、
mvn test -Dtest=[テストクラス名]オプションを使用します。 - 一時的にテストをスキップしたい場合は、
mvn package -DskipTestsオプションを使用します。ただし、テストは品質保証のために重要なので、原因究明が第一です。
11.4 ネットワークの問題 (リポジトリに接続できない)
ファイアウォール、プロキシ設定、またはインターネット接続そのものの問題により、Mavenがリモートリポジトリに接続できない場合に発生します。
原因:
- インターネット接続がない。
- 企業のファイアウォールによって外部への接続がブロックされている。
- プロキシサーバー経由での接続が必要なのに設定されていない、または設定が間違っている。
対処法:
- インターネット接続ができているか確認します。
- 会社のネットワーク環境でMavenを使用している場合は、ネットワーク担当者に確認し、必要なプロキシ設定情報を入手します。
- 取得したプロキシ設定情報を、Mavenの
settings.xmlファイル (~/.m2/settings.xml) に記述します。
“`xml
11.5 デバッグ方法
問題の原因が特定できない場合は、デバッグオプションを付けてMavenを実行し、詳細なログを分析することが有効です。
-e(–errors): エラー発生時の詳細なスタックトレースなどを出力します。-X(–debug): Mavenの内部処理、環境設定、クラスパス、使用されているプラグイン、ゴール実行の詳細など、非常に詳細なデバッグログを出力します。出力量が膨大になることがありますが、原因特定に役立ちます。
bash
mvn clean install -e
mvn clean install -X > maven_debug.log # 出力をファイルに保存して分析
12. MavenとIDEの連携
実際のJava開発では、多くの場合Eclipse, IntelliJ IDEA, VS Codeといった統合開発環境(IDE)を使用します。主要なIDEはMavenとの強力な連携機能を備えています。
IDEを使用することで、以下のようなMaven関連の操作をGUIから簡単に行えるようになります。
- Mavenプロジェクトのインポート: 既存のMavenプロジェクト(
pom.xmlファイルがあるディレクトリ)をIDEにインポートし、プロジェクト構造を認識させることができます。 - 依存関係の解決と表示:
pom.xmlに記述された依存関係を自動的にダウンロードし、プロジェクトのビルドパスに設定します。IDE上で依存関係ツリーを確認したり、競合を検出したりできる機能を提供するIDEもあります。 - ビルドライフサイクルの実行: IDEのメニューやビューから、
clean,compile,test,package,installといったMavenライフサイクルフェーズや、特定のプラグインゴールを実行できます。 pom.xmlの編集支援:pom.xmlのXML構造に対する入力補完機能(依存関係のgroupId, artifactId, versionなど)や、構文チェック機能が提供されます。- ローカルリポジトリの管理: IDEからローカルリポジトリの内容を確認できる場合もあります。
主要IDEでのMaven連携:
- Eclipse: Eclipse IDE for Java EE Developers (または Maven Integration for Eclipse (m2e) プラグインを追加) でMavenプロジェクトをそのままインポートできます。「Maven」ビューからライフサイクルゴールの実行や依存関係ツリーの確認が可能です。
- IntelliJ IDEA: Ultimate版、Community版ともに強力なMaven連携機能を標準で備えています。「Open」または「Import Project」でMavenプロジェクトの
pom.xmlを選択すればプロジェクトとして認識されます。Mavenツールウィンドウから各種操作が可能です。 - VS Code: Extension Marketplaceから「Maven for Java」などの拡張機能をインストールすることで、Mavenプロジェクトの認識、依存関係管理、コマンド実行などの機能を利用できます。
IDEと連携することで、コマンドライン操作だけでなく、GUIによる直感的な操作や、IDEの持つコード編集・デバッグ機能と統合されたスムーズなMaven開発が可能になります。
13. まとめ
この記事では、Mavenを初めて使う方に向けて、その基本的な概念、インストール方法、プロジェクト作成、pom.xml の詳細、コマンドライン操作、依存関係管理、プラグイン、そして応用的なトピックとトラブルシューティングについて、詳細に解説しました。
MavenはJava開発において非常に強力なツールであり、そのメリットは計り知れません。
- 標準化: プロジェクト構造とビルドプロセスが標準化されるため、チーム開発や新しいプロジェクトへの参加が容易になります。
- 依存関係管理: 外部ライブラリの管理から解放され、依存関係の衝突を解決するためのツールも提供されます。
- 自動化: コンパイル、テスト、パッケージングといった一連のビルド作業を自動化できます。
- 拡張性: プラグインによって様々な機能を容易に追加できます。
Mavenを使いこなすことは、Java開発者としてのスキルアップに直結します。最初は概念が少し難しく感じるかもしれませんが、実際に手を動かしてプロジェクトを作成し、依存関係を追加し、ビルドコマンドを実行してみることで、徐々に理解が深まっていくはずです。
この記事を足がかりに、ぜひあなたのJava開発にMavenを取り入れてみてください。
次に学ぶべきこと
Mavenの基礎をマスターしたら、さらに以下のトピックに進んでみましょう。
- マルチモジュールプロジェクトの構築: より大きなシステムを複数のMavenモジュールに分割して管理する方法。
- Mavenプロファイルの詳細: 環境に応じたビルド設定の切り替えをより深く理解する。
- Maven Release Plugin: リリースプロセスを自動化する方法。
- settings.xml の詳細: ユーザー固有の設定や、組織全体のMaven設定(リポジトリミラー、プロキシなど)を管理する方法。
- リポジトリマネージャー (Nexus / Artifactory): 組織内の共有リポジトリを構築し、ライブラリのキャッシュや自社成果物の共有を効率化する方法。
- CI/CDツールとの連携: Jenkins, GitLab CI, GitHub ActionsなどのCI/CDツールとMavenを連携させ、コードコミットをトリガーに自動ビルドや自動テスト、デプロイを実行する方法。
これらの知識を身につけることで、あなたはより効率的で、堅牢なJava開発を行えるようになるでしょう。
長文となりましたが、最後までお読みいただきありがとうございました。この記事が、あなたのMaven学習の一助となれば幸いです。
さあ、Mavenを使った快適なJava開発を始めましょう!