はじめに
自分たちのプロジェクトではビルドツールを使ったことが無かったので、導入に向けてMavenについてまとめてみました。
本記事は自分自身の理解とプロジェクトメンバーへ展開するのに必要な情報をまとめる目的で作成しています。
またMaven3を利用するためこれを前提にした記述となります。
Mavenとは
Mavenはプロジェクト管理ツールで、Javaプログラムのビルド(jarライブラリの管理・コンパイル・テスト・WARやJARの生成)の実行を制御したり、結果のレポートが生成できます。
また、プラグインを拡張することでビルドやレポート作成に機能を追加できます。
Mavenは実行させたい処理をpom.xml(Project Object Model)に記述することで、細かい指示を制御できます。
例えば、利用するjarライブラリのバージョンを指定したり、DB接続先などの環境依存設定を指定してWARの生成ができます。
pom.xml
概要のみまとめます。
詳しくはMaven-POM Referenceをご確認ください。
groupId/artifactId/versionは必須の設定値です。
要素 | 説明 |
---|---|
groupId | 組織やプロジェクトでユニークなID。プロジェクトのパッケージ構造に従って定義するケースもある。 |
artifactId | プロジェクトを識別する名称 |
version | プロジェクトのバージョン |
packaging | プロジェクトの成果物の状態。warやjarなどを指定できます。 |
dependencies | プロジェクトが参照するライブラリ |
parent | 参照する親POMを指定します。 |
dependencyManagement | 依存するライブラリのひな形を定義します。 |
modules | マルチ・プロジェクトが管理するモジュールを定義します。 |
properties | このタグ内で宣言した値はpom内で${X}で参照することができます。JDKのVersionやEncordingなどプロジェクト内で汎用的に参照する値を定義したい場合に利用します。 |
build | ビルドの際に実行するpluginを定義します。 |
reporting | siteの際に実行するpluginを定義します。 |
repositories | リモート以外に検索するリポジトリを定義します。 |
pluginRepositories | リモート以外で検索したいPlugin専用リポジトリを定義します。 |
profiles | mavenの実行環境別の設定情報を定義します。例えば本番用・ステージング用・開発用と環境の切り替えができます。 |
バージョニング
versionタグで指定するプロジェクトのバージョン管理は、セマンティック バージョニングに従うのが一般的です。
すなわち、「X.Y.Z(メジャー.マイナー.パッチ)- 識別子(alpha/beta/m/rc/SNAPSHOTなど)」で表します。
EclipseやIntelliJ IDEAで新規のMavenプロジェクトを作成するときのVersionのデフォルトは0.0.1-SNAPSHOTです。
依存性解決
依存性解決はMavenにおける重要な機能であり、プロジェクトが依存するライブラリ(外部jar)を管理します。
依存性[dependency]をpom.xmlに記述することで、必要なライブラリを自動的にMavenのリポジトリからダウンロードします。
この機能は必要なライブラリを自分でサイトからダウンロードしてビルドパスに追加したり、バージョン管理システムへのコミットを不要にします。
また、開発環境によってクラスパスが異なることで生じる環境設定のコンフリクトも解消できます。
Mavenリポジトリ
Mavenリポジトリはライブラリが管理されている場所です。
Mavenはビルドを実行すると必要なライブラリをリポジトリからダウンロードします。
プロジェクトの成果物もリポジトリへアップロードして、他のプロジェクトが利用できます。
セントラルリポジトリ
インターネットに公開されているMavenの公式リポジトリです。
ここには様々なライブラリのversionが公開されており、必要なライブラリをローカルにダウンロードできます。
セントラルリポジトリ
リモートリポジトリ
セントラルリポジトリと同じようにライブラリを管理します。Sonatype NEXUSなどを利用して独自のリモートリポジトリも構築できます。
例えば以下のようなリポジトリは、リモートリポジトリになります。
- サードパーティ独自のリポジトリ
- セントラルリポジトリのミラー
- 社内ネットワーク限定のプライベートリポジトリ
ローカルリポジトリ
開発環境に構築されるリポジトリです。Mavenがライブラリを検索する際はまずローカルリポジトリから探し、無い場合にセントラルリポジトリやリモートリポジトリを検索してダウンロードします。
ローカルリポジトリは~/.m2/repository
に置かれます。
Scope
scopeを指定するとclasspathにライブラリを定義する状況が指定できます。指定しなかった場合はcompile
となります。
Scope | 説明 |
---|---|
compile | 全ての状況においてclasspathに定義します。 |
provided | compileと同等ですが成果物には含まれません。主にJDKやServletAPIなど成果物がデプロイされる環境側でライブラリが用意されている場合に指定します。 |
runtime | 成果物の実行時に必要となるライブラリで成果物に含まれます。 |
test | testコードを実行する時にコンパイル•実行する必要があるライブラリ。JUnitやMockitoなどが該当する。成果物には含まれません。 |
system | providedと同等ですが、ライブラリはリポジトリではなくsystemPath で指定したパスを参照します。 |
Mavenを実行する
ゴール
Mavenで実行する処理は機能ごとに『ゴール』と呼ばれます。
『ゴール』はプラグインから提供されており、mvn plugin名:Goal名
で実行します。
1つのプラグインは複数のゴールを持ちます。
フェーズ
Mavenでは行いたいことを『フェーズ』と呼びます。
フェーズには複数の『ゴール』が紐づけられており、行いたいフェーズをmvn phase名
で実行すると『フェーズ』に紐づく『ゴール』を順番に実行します。
フェーズは、後述するライフサイクルによって実行する順番が決められています。
ビルドのライフサイクル
Mavenのビルドはライフサイクルに従って、決められた『フェーズ』を順番に実行します。
定義されているライフサイクルは3種類です
defaultサイクル
文字通り標準のライフサイクルです。Phaseが全部で23個あるため、ここでは主なPhaseのみを説明します。
(記載しなかったPhaseは、次のPhaseの準備処理や前のPhaseの後処理になります。)
『成果物[artifact]』とはwarやjarなどのことを指します。
No. | Phase | 概要 |
---|---|---|
1 | validate | プロジェクトの正当性を検証 |
7 | compile | プロジェクトのコンパイル |
15 | test | ユニットテストの実行 |
17 | package | 成果物の作成(パッケージング) |
21 | verify | 成果物の検証 |
22 | install | 成果物をローカルリポジトリに配置 |
23 | deploy | 成果物をリモートリポジトリに配置 |
例えば、mvn package
を実行すると、validateからpackageまでの17のフェーズを実行し、アーティファクトを生成します。
mvn deploy
まで実行すると、validateからdeployまでの23のフェーズ全てを実行します。
cleanサイクル
cleanサイクルは、ビルドによって生成された一時ファイルを削除するためのライフサイクルです。
一時ファイルとはcompileやtestなどで、ローカルに生成されたclassやリソースファイルのことを指します。
(通常のMavenプロジェクトでは、targetディレクトリに出力されるファイル)
リビルドする際に残っていた一時ファイルが再利用される場合があるので、defaultサイクルでビルドを実行する前には必ずcleanも実行すると良いです。
例 mvn clean package
No. | Phase | 概要 |
---|---|---|
1 | pre-clean | 一時ファイル削除の前処理 |
2 | clean | 一時ファイルの削除 |
3 | post-clean | 一時ファイル削除の後処理 |
siteサイクル
siteライフサイクルではプロジェクトのドキュメントを生成します。
例えば後述するプラグインを利用して、javadocの生成やcheckstyles、FindBugsなどの静的解析結果レポート、テスト結果やカバレッジレポートなどを生成します。
ビルドと同時にsiteも指定して実行すると、ビルド結果のドキュメントが生成します。
例 'mvn install site'
No. | Phase | 概要 |
---|---|---|
1 | pre-site | ドキュメント生成の前処理 |
2 | site | ドキュメントの削除 |
3 | post-site | ドキュメント作成の後処理 |
3 | site-deploy | ドキュメントを指定したWebサーバーに配置 |
プラグイン
プラグインはJavaで書かれたMavenの機能です。ライフサイクルのフェーズに紐づくゴールもプラグインが提供しています。これ以外にも様々なプラグインが公開されており、また独自のプラグインも作成できます。
それぞれのプラグインで使い方が異なるため各プラグインのHPを確認してください。
ビルド(build)
主にdefaultライフサイクルで実行したいプラグインを定義します。
レポート(report)
site実行時のレポートを出力するためのプラグインを定義します。
例えばcheckstyleやfindbugsなどの静的解析結果が確認できたり、プロジェクトコードのjavadocを閲覧できます。
マルチモジュールプロジェクト
Mavenでは一つのプロジェクトを役割やサービスごとに『モジュール』で分けて管理することができます。
例えばcoreモジュールやpluginモジュール、共通機能モジュールなどです。
このようなプロジェクト構成の場合、プロジェクト全体を管理する親モジュールのpom.xmlにモジュール構成や共通の設定を定義して、各モジュールのpom.xmlで継承することができます。
マルチモジュールプロジェクトの構成例
マルチモジュールプロジェクトの親モジュールにpom.xmlでは以下のような設定を行います。
- packagingに
pom
を指定します。 - modulesに管理するモジュールのArtifactIdを指定します。
- propertiesで管理した情報はモジュールのpom.xmlでも参照できます。
- dependencyManagementやpluginManagementにdependencyやpluginのひな形を定義することができます。
モジュール側のpom.xmlではgroupIdとartifactIdを指定するだけでひな形に則った定義を利用できますし、オーバーライドもできます。
子のモジュールではparentタグで親モジュールのgroupId/artifactId/versionを指定して継承します。
開発プロジェクトへの導入例
グループで開発中のプロジェクトをMavenプロジェクトに移行するまでを例とします。
Eclipseではプロジェクトを右クリック > 構成 > Mavenプロジェクトへ変換
により既存プロジェクトをMavenプロジェクトに変換できますが、初めてのMavenプロジェクト作成なので一から作ったプロジェクトにモジュールをコピーする方法としました。
前提
- Windows
- All in One Eclipseを使用し、Mavenプラグインがインストール済み。
- 既存プロジェクトはTomcatプロジェクトです。
- DatabaseはOracleを利用しているのでOJDBCを利用する。
Mavenのインストール
詳細はMavenのインストールを参照してください。
圧縮ファイルを解凍し、環境変数PATHにbinフォルダを通す。
コマンドプロンプトを開きmvn --version
でversion情報が表示されればOKです。
次にMavenの作業フォルダ.m2を作成します。
作業フォルダは一般的にユーザディレクトリ~/.m2
に作成します。
合わせて作業フォルダの配下に以下のディレクトリとファイルも作成しておきます。
~/.m2/repository
ローカルリポジトリとなるディレクトリです。
~/.m2/setting.xml
ユーザー設定ファイルです。
proxyの設定
proxyを介してインターネットアクセスしている場合は、proxyの設定が必要です。
~/.m2/setting.xml
に以下のように記述します。
※認証Proxyでなければ、usernameとpasswordは不要です。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<proxies>
<proxy>
<id>http_proxy</id>
<active>true</active>
<protocol>http</protocol>
<username>認証アカウント</username>
<password>認証パスワード</password>
<host>proxyサーバのIPアドレス</host>
<port>proxyサーバのポート番号</port>
</proxy>
<proxy>
<id>https_proxy</id>
<active>true</active>
<protocol>https</protocol>
<username>認証アカウント</username>
<password>認証パスワード</password>
<host>proxyサーバのIPアドレス</host>
<port>proxyサーバのポート番号</port>
</proxy>
</proxies>
</settings>
Eclipseの設定
- Window > Preferences > Maven > User Settingsを選択します。
- User Settingに、
~/.m2/setting.xml
を指定します。 - Local Repositoryに、
~/.m2/repository
を指定します。
Mavenプロジェクトの作成
今回は既存のTomcatプロジェクトをMavenプロジェクトに変換します。
以下のようなマルチモジュール構成で管理します。
project
├─ main module
├─ sub module1
├─ sub module2
└─ sub module3
- main moduleはWebアプリです。
- sub module1-3はmain moduleが利用するライブラリソースです。
- これらモジュールをprojectで複合管理します。
親pomの作成
マルチモジュールを構成する親pomを作成します。
- File > New > Maven project を選択します。
- New Maven projectで「create a simple project(skip archetype selection)」をチェックしNextを押します。
- Configure projectのArtifactで以下を入力したら、Finishを押します。
groupId・・・・プロジェクトでユニークなID(jp.co.会社名.製品名/com.製品名など)
artifactId・・・プロジェクトの識別名称
version ・・・ バージョン(まずはデフォルトの0.0.1-SNAPSHOTでよい。)
package ・・・ pom
作成するとsrcフォルダとpom.xmlが出来ます。今回はsrcは不要なため削除します。
Mavenがコンパイルで利用するJaveバージョンの指定
デフォルトではJava5(1.5)が指定されているため、pom.xmlにpropertyを開き、バージョンを指定します。
親pomに指定することで、sub moduleにも反映されます。またsub moduleでバージョンを変えたい場合はそのモジュールのpom.xmlで同様にpropertyを指定します。
<properties>
<java-version>1.8</java-version>
<maven.compiler.source>${java-version}</maven.compiler.source>
<maven.compiler.target>${java-version}</maven.compiler.target>
</properties>
sub moduleの作成
親プロジェクト配下にsub moduleを作成します。今回作るsub moduleは、後述するweb moduleで参照するjarライブラリとなります。
- 親プロジェクトを右クリック > Maven > New Maven Module Project を選択します。
- New Maven projectで「create a simple project(skip archetype selection)」をチェックを外します。
- Module Nameに、モジュールの名前を入力、Parent Projectに親プロジェクトが指定されているのを確認しNextを押します。
- Select an Archetypeで、Artifact ID:maven-archetype-quickstartを選択しNextを押します。
- Configure projectのArtifactで以下を確認・入力したらFinishを押します。
groupId・・・・親プロジェクトと同じ
artifactId・・・module name
version ・・・ 親プロジェクトと同じ
package ・・・ jar
以下のようなフォルダ構成でsub moduleが作られます。
sub module
├src/main/java
└src/test/java
main module(Web module)の作成
今回のMain moduleとなるWebアプリケーションモジュールを作成します。
- 親プロジェクトを右クリック > Maven > New Maven Module Project を選択します。
- New Maven projectで「create a simple project(skip archetype selection)」のチェックを外します。
- Module Nameに、モジュールの名前を入力、Parent Projectに親プロジェクトが指定されているのを確認しNextを押します。
- Select an Archetypeで、Artifact ID:maven-archetype-webappを選択しNextを押します。
- Configure projectのArtifactで以下を確認・入力したらFinishを押します。
groupId・・・・親プロジェクトと同じ
artifactId・・・module name
version ・・・ 親プロジェクトと同じ
package ・・・ war
以下のようなフォルダ構成でweb moduleが作られます。
web module
├src/main/resources
└src/main/webapp (webアプリのルートフォルダ。この配下にMETA-INF、WEB-INFが存在します。)
maven-archetype-webappでは、javaのソースフォルダやtestフォルダが作成されませんので作成します。
web module
├src/main/java
├src/main/resources
├src/main/webapp
└src/test/java
依存性の解決
それぞれのmoduleのpom.xmlにdependencyを追加します。
またEclipseでは専用のMaven POM Editorを利用すると視覚的に分かりやすく入力することができます。
Maven POM Editorでpom.xmlを開き、Dependenciesタブを開きます。
左側のDependenciesのAddをクリックし、Select Dependencyウィンドウを開きます。
追加したいライブラリのGroup ID/Artifact ID/Version/Scopeを指定しOKを押します。
分からない場合は、真ん中のEnter・・・・で検索ができます。
また追加したライブラリを親PomのDependency Managementに追加して、他のSub moduleでも共通して参照させる場合はManagedを押します。
親pomに追加するライブラリを左側から選択し、右側の親Pomを選択してOKを押します。
これで親PomのDependency Managementにライブラリが追加されますが、他のSub Moduleで利用する場合はそのpom.xmlを開きライブラリを追加してください。
プラグインの指定
以下のプラグインを実行し、mvn site
でレポートを出力するようにします。
レポートはJenkinsを利用してビルドすると、ビルドの結果に出力することもできます。
- checkstyle ※configフォルダを作り、設定ファイル(google_checks.xmなど)を置きます。
- findBugs
- JaCoCo
- javadoc
設定例はこちらにあります。(自分の記事ですが。)
環境依存の設定
pom.xmlはprofile
タグを持ちます。例えばある設定値を状況に応じて変えたい場合などに利用します。
よく使われる方法としてはDBの接続先があると思います。
例えば接続先の定義をresourcePropertyファイル
jdbc.url=jdbc:oracle://xxxxxxxx:1521/ora
jdbc.username=username
jdbc.password=password
開発環境(dev)、検証環境(staging)、本番環境(prod)の3つの環境に対してビルドをするにはprofileで以下のように設定します。
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jdbc.url>jdbc:oracle://xxxxxxxx:1521/oradev</jdbc.url>
<jdbc.username>開発環境のusername</jdbc.username>
<jdbc.password>開発環境のpassword</jdbc.password>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<jdbc.url>jdbc:oracle://xxxxxxxx:1521/orastaging</jdbc.url>
<jdbc.username>検証環境のusername</jdbc.username>
<jdbc.password>検証環境のpassword</jdbc.password>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<jdbc.url>jdbc:oracle://xxxxxxxx:1521/oraprod</jdbc.url>
<jdbc.username>本番環境のusername</jdbc.username>
<jdbc.password>本番環境のpassword</jdbc.password>
</properties>
</profile>
</profiles>
activeByDefault=true
はデフォルト値となるので、何も指定せずにビルドしたりIDE上でWebアプリを起動した場合に参照します。
検証環境や本番環境用に切り替えたい場合はmvn -P staging package
,man -P prod package
と-P
オプションでprofileのidを指定します。
環境に依存する設定ファイルは専用のモジュールで管理し、Webアプリモジュールと切り離すことで、warファイルの再利用が可能になります。
これはプロパティの一部を切り替える場合の方法ですが、profileではその以外にもpropertyファイル自体を切り替えることも可能です。
例えばpropertyファイルを環境別に以下のようなディレクトリ管理を行っているとします。
src/main/resources/··· 開発環境(デフォルト)のリソースファイルのディレクトリ
resources/staging/··· 検証環境のリソースファイルのディレクトリ
resources/prod/··· 本番環境のリソースファイルのディレクトリ
環境ごとにsrc/main/resources/
下のファイルを入れ替える場合のpom.xmlは以下の通りです。
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<resources.directory>${basedir}/src/main/resources</resources.directory>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<resources.directory>${basedir}/resources/staging</resources.directory>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<resources.directory>${basedir}/resources/prod</resources.directory>
</properties>
</profile>
</profiles>
···
<build>
<resources>
<resource>
<directory>${resources.directory}</directory>
</resource>
</resources>
</build>
buildタグでresourcesのディレクトリのpathを${resources.directory}
で定義し、それに対して環境別のディレクトリPathをprofileで定義しています。
こうすることで環境に依存しないwarが出来上がり、別の環境で再利用が可能になるからです。
尚、環境設定ファイルはwebアプリモジュールではなく専用モジュールで管理し参照ライブラリとして外出しにし、warには含めない方法が良いと思います。
環境依存ファイルに対するビルドの考え方については、Terasolunaのガイドラインにも説明があります。
Terasoluna - 3.5.開発プロジェクトのビルド
今回のプロジェクトでも開発環境/検証環境/本番環境と3つのDB接続先があるため、profileを使いたかったのですが、接続先の設定ファイルがresourceフォルダ配下では無かったことやresourceフォルダ配下のファイルの数が多かったので、それらを全て管理するのも難しく、まずはprofileを利用せずに移行しました。
こちらの記事で試してみました。
OJDBCドライバーの参照方法
OJDBCドライバー(oracle.jar)はMavenリポジトリーでは管理されていないため、以下のいずれかの手順でMavenプロジェクトに取り込む必要があります。
(本プロジェクトではOracle.jarはruntimeとし、本番サーバーではTomcatのlibにjarを置くようにしています。)
1. systemスコープでdependencyに登録する
- Oracle公式サイトから必要なoracle.jarをダウンロードする。
- oracle.jarをプロジェクトの任意の場所に配置する。(libフォルダなど)
- pom.xmlのdependencyに追加する。(groupId,artifactId,versionを通常通り書く。)
- dependencyのscopeをSYSTEMとし、SYSTEMPATHで配置したoracle.jarまでのPATHを指定する。
※プロジェクトのビルドパスにも外部jarで設定しないと、開発環境でTomcatを立ち上げた時にOracleDBに接続されなかったので気をつけてください。
2. ローカルリポジトリにoracle.jarを置く
- Oracle公式サイトから必要なoracle.jarをダウンロードする。
- oracle.jarをローカルリポジトリ
~/.m2/repository
に置く。 - pom.xmlのdependencyに追加する。(groupId,artifactId,versionを通常通り書く)
※本プロジェクトの成果物にはoracle.jarを含めないため、scopeはruntimeとします。
3. Oracleの公式Mavenリポジトリから参照できるようにする。
この方法自体は未確認・未検証です。
ただ各開発環境でOTNライセンスの設定が必要なことやEclipseだと初回はmvnコマンドを実行する必要があるようです。
ビルドの実行
- ビルドを実行するプロジェクトやモジュールを右クリック > Run As > Maven build を選択します。
- Mavenの設定画面が表示されますので、Goalsに実行したいGoalやPhaseを入力します。例
clean compile
clean install site
など - コンソールにMavenの実行結果が表示されます。Successとなっていれば完了です。Errorとなっていた場合はその原因を解消します。
- installを実行していた場合、ローカルリポジトリにwarファイルやjarファイルがアップロードされます。
Server設定
Mavenとは関係ありませんが、EclipseでWebアプリを実行する場合、これまではTomcatプラグインをインストールしていましたが、今回はWTPプラグインを利用したTomcatアプリケーションの実行方法を説明します。
(EclipseにWTPプラグインがインストールされている前提です)
- Serverビューを開き、右クリック > New > Serverを選択します。
- Define a New Serverで、Apache > Tomcat vX.X Serverを選択します。(X.Xは利用したいTomcatのバージョン)
- Tomcat Serverの設定画面が表示されるので、Tomcat installation directoryで、ローカルにあるTomcatディレクトリを指定するか、Download and InstallボタンからTomcatをインストールします。
- JREも同じように、ローカルかインストールを選択しFinishを押します。
- Severビューに戻り、追加されたTomcat vX.X Serverを右クリック > Add and Removeを選択します。
- Availableに実行できるWebモジュールが表示されるので、選択してAddを押し、Finishします。
- Webモジュールが追加できたら、Tomcat vX.X Serverを右クリック > Start でTomcatが起動します。
※Startのときにエラーが出て起動されない場合がありますが、Tomcat vX.X Serverを右クリック > clean を実行してからstartしたり、少し時間をおいてからStartすると正常に起動されました。
参考サイト
Apache Maven Project
Wikipedia
Maven基礎
Maven3の始め方
Maven2、Maven3のPOMの書き方まとめ〜全体概要編〜
Mavenのビルドのライフサイクル
Java製アプリを Eclipse から実行したことしかない新人に「ビルドツールとは?」を説明してみる…そして CI へ
6.プロファイル|TECHSCORE