Help us understand the problem. What is going on with this article?

TomcatプロジェクトにMavenを導入する

More than 3 years have passed since last update.

はじめに

自分たちのプロジェクトではビルドツールを使ったことが無かったので、導入に向けて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は不要です。

setting.xml
<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の設定

  1. Window > Preferences > Maven > User Settingsを選択します。
  2. User Settingに、~/.m2/setting.xmlを指定します。
  3. 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を作成します。

  1. File > New > Maven project を選択します。
  2. New Maven projectで「create a simple project(skip archetype selection)」をチェックしNextを押します。
  3. 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を指定します。

pom.xml[JDK version]
<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ライブラリとなります。

  1. 親プロジェクトを右クリック > Maven > New Maven Module Project を選択します。
  2. New Maven projectで「create a simple project(skip archetype selection)」をチェックを外します。
  3. Module Nameに、モジュールの名前を入力、Parent Projectに親プロジェクトが指定されているのを確認しNextを押します。
  4. Select an Archetypeで、Artifact ID:maven-archetype-quickstartを選択しNextを押します。
  5. 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アプリケーションモジュールを作成します。

  1. 親プロジェクトを右クリック > Maven > New Maven Module Project を選択します。
  2. New Maven projectで「create a simple project(skip archetype selection)」のチェックを外します。
  3. Module Nameに、モジュールの名前を入力、Parent Projectに親プロジェクトが指定されているのを確認しNextを押します。
  4. Select an Archetypeで、Artifact ID:maven-archetype-webappを選択しNextを押します。
  5. 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で以下のように設定します。

pom.xml
<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は以下の通りです。

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に登録する

  1. Oracle公式サイトから必要なoracle.jarをダウンロードする。
  2. oracle.jarをプロジェクトの任意の場所に配置する。(libフォルダなど)
  3. pom.xmlのdependencyに追加する。(groupId,artifactId,versionを通常通り書く。)
  4. dependencyのscopeをSYSTEMとし、SYSTEMPATHで配置したoracle.jarまでのPATHを指定する。

※プロジェクトのビルドパスにも外部jarで設定しないと、開発環境でTomcatを立ち上げた時にOracleDBに接続されなかったので気をつけてください。

2. ローカルリポジトリにoracle.jarを置く

  1. Oracle公式サイトから必要なoracle.jarをダウンロードする。
  2. oracle.jarをローカルリポジトリ~/.m2/repositoryに置く。
  3. pom.xmlのdependencyに追加する。(groupId,artifactId,versionを通常通り書く)

※本プロジェクトの成果物にはoracle.jarを含めないため、scopeはruntimeとします。

3. Oracleの公式Mavenリポジトリから参照できるようにする。

Oracle公式のMavenリポジトリを使う方法

この方法自体は未確認・未検証です。
ただ各開発環境でOTNライセンスの設定が必要なことやEclipseだと初回はmvnコマンドを実行する必要があるようです。

ビルドの実行

  1. ビルドを実行するプロジェクトやモジュールを右クリック > Run As > Maven build を選択します。
  2. Mavenの設定画面が表示されますので、Goalsに実行したいGoalやPhaseを入力します。例 clean compile clean install siteなど
  3. コンソールにMavenの実行結果が表示されます。Successとなっていれば完了です。Errorとなっていた場合はその原因を解消します。
  4. installを実行していた場合、ローカルリポジトリにwarファイルやjarファイルがアップロードされます。

Server設定

Mavenとは関係ありませんが、EclipseでWebアプリを実行する場合、これまではTomcatプラグインをインストールしていましたが、今回はWTPプラグインを利用したTomcatアプリケーションの実行方法を説明します。
(EclipseにWTPプラグインがインストールされている前提です)

  1. Serverビューを開き、右クリック > New > Serverを選択します。
  2. Define a New Serverで、Apache > Tomcat vX.X Serverを選択します。(X.Xは利用したいTomcatのバージョン)
  3. Tomcat Serverの設定画面が表示されるので、Tomcat installation directoryで、ローカルにあるTomcatディレクトリを指定するか、Download and InstallボタンからTomcatをインストールします。
  4. JREも同じように、ローカルかインストールを選択しFinishを押します。
  5. Severビューに戻り、追加されたTomcat vX.X Serverを右クリック > Add and Removeを選択します。
  6. Availableに実行できるWebモジュールが表示されるので、選択してAddを押し、Finishします。
  7. 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

kazokmr
自分のための記録用です
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away