Maven3 チュートリアル

Table of Contents

1 Hello Maven

1.1 この章のねらい

  • とにかくMavenを動かして慣れよう!

1.2 TODO archetypeからプロジェクト作成してみよう

シンプルなpom.xmlから学習するため、 デフォルトのアーキタイプからプロジェクトを生成します。

# 新規ディレクトリを作成
mkdir example/hello
cd example/hello
# アーキタイプからMavenプロジェクトを作成
mvn archetype:generate

アーキタイプの種類を選べと言われます。

Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 705:

そのままエンターキーを押し、デフォルトのmaven-archetype-quickstartを選択します。

その他入力を求められますので以下のように入力します(デフォルト値)。

要素 入力例 
アーキタイプのバージョン 1.1
groupId com.example
artifactId hello
version 1.0-SNAPSHOT
package com.example

1.3 TODO pom.xmlを見てみよう

作成されたpom.xmlを眺めてみます。

# pom.xmlを開く
less pom.xml

1.3.1 pom.xml

<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.example</groupId>
  <artifactId>hello</artifactId>
  <version>1.0.0</version>
  <packaging>jar</packaging>

  <name>hello</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

1.4 TODO ビルドしてみよう

コマンドを実行して、成果物が作成されることを確認しましょう。

コマンド target配下の成果物 説明 
mvn compile classes/ classファイル
mvn test test-classes/,surefire-reports/ classファイルとレポート
mvn package hello-1.0-SNAPSHOT.jar jarファイル
mvn install - .m2/repositoryに配置される
mvn site site レポート
mvn clean - targetが削除される

1.5 暗黙の設定値を確認しよう

mavenのpom.xmlは多くのデフォルト設定値があります。 また、他のpom.xmlから値を引き継ぐこともできます。

今のpom.xmlがどういう状態であるか確認する場合、 以下のコマンドが頼りになります。

1.5.1 TODO 完全な設定値を出力する

settings.xmlやparentのpomを含めた設定値を出力します。

# 標準出力に出力する場合
mvn help:effective-pom

# ファイルに出力する場合
mvn help:effective-pom -Doutput=epom.xml
pom.xmlの要素 説明
<sourceDirectory> ソース置き場
<testSourceDirectory> テストソース置き場
<outputDirectory> classファイル等の出力先ディレクトリ
<testOutputDirectory> テストclassファイル等の出力先ディレクトリ
<resources> リソース置き場
<testResources> テストリソース置き場

1.5.2 TODO 依存関係を出力する

mvn dependency:tree
[INFO] com.example:hello:jar:1.0-SNAPSHOT
[INFO] \- junit:junit:jar:3.8.1:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

1.6 デフォルトのビルド設定を試してみよう。

1.6.1 TODO コンパイル設定

ソースを編集してみる。

vi src/main/java/com/example/App.java
public static void main( String[] args )
{
    System.out.println( "Hello Maven!" );
}

実行します。

java -cp target/classes com.example.App

1.6.2 TODO テストコンパイル設定

src/main配下のクラスで、junitのクラスを使ってみる。

public static void main( String[] args )
{
    // JUnitのクラスを使ってみる。
    junit.framework.TestCase.assertTrue(true);
    System.out.println( "Hello World!" );
}

テストを実行します。

mvn test
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project hello: Compilation failure
[ERROR] /home/hoge/mvn3-tutorial/example/hello/src/main/java/com/example/App.java:[11,24] パッケージjunit.frameworkは存在しません

なぜコンパイルは失敗したのでしょうか?

1.6.3 TODO リソースの配置

hoge.txtを配置してコンパイルしてみよう。 hoge.txtはコピーされる?理由は?

  1. src/main/java
    # src/main/java配下にファイルを作成
    touch src/main/java/hoge.txt
    # コンパイル実行
    mvn clean compile
    # 結果確認
    ls target/classes
    
  2. src/main/resources
    # src/main/resourcesにファイルを移動
    mv src/main/java/hoge.txt src/main/resources/
    # コンパイル実行
    mvn clean compile
    # 結果確認
    ls target/classes
    

1.7 設定を変更してみよう

1.7.1 TODO versionを変えてみる。

<groupId>com.example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
mvn clean package
ls target

1.7.2 TODO dependencyを変えてみる。

  1. JUnit4.12にしてみる

    http://search.maven.org/ で検索する。

    http://search.maven.org/#artifactdetails%7Cjunit%7Cjunit%7C4.12%7Cjar

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    

    依存関係はどう変化しましたか?

    mvn dependency:tree
    
    [INFO] com.example:hello:jar:1.0.0
    [INFO] \- junit:junit:jar:4.12:test
    [INFO]    \- org.hamcrest:hamcrest-core:jar:1.3:test
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    

    org.hamcrest:hamcrest-coreというライブラリは、なぜ現れたのでしょうか?

  2. TODO 好きなライブラリを足してみよう
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>1.3.2.RELEASE</version>
    </dependency>
    

    依存関係はどう変化しましたか?

    mvn dependency:tree
    

1.8 TODO helpを表示してみよう

mvn -h

1.8.1 出力結果(抜粋)

usage: mvn [options] [<goal(s)>] [<phase(s)>]

Options:
 -D,--define <arg>                      Define a system property
 -f,--file <arg>                        Force the use of an alternate POM
                                        file (or directory with pom.xml).
 -h,--help                              Display help information
 -o,--offline                           Work offline
 -P,--activate-profiles <arg>           Comma-delimited list of profiles
                                        to activate
 -s,--settings <arg>                    Alternate path for the user
                                        settings file
 -U,--update-snapshots                  Forces a check for missing
                                        releases and updated snapshots on
                                        remote repositories
 -v,--version                           Display version information
 -X,--debug                             Produce execution debug output

2 依存関係

2.1 この章のねらい

  • Mavenの目玉機能である依存関係の管理を理解しよう
  • PJで、ライブラリをどう管理・連携するかを理解しよう

2.2 アーティファクト

mavenでは、あるmavenモジュールから作り出される成果物(典型的にはjarやwarファイル)を アーティファクト(artifact ≒ 成果物)と呼びます。

2.3 推移的依存関係

あるアーティファクトAが別のアーティファクトBに依存しているとします。 自分のモジュールにアーティファクトAを<dependecy>に加えた場合、 アーティファクトBも依存関係に含まれます。 これを推移的依存関係といいます。

推移的依存関係のおかげで、自分が使いたいライブラリを<dependecy>に追加するだけで、 間接的に必要なライブラリも芋づる式に取得できます。

2.3.1 JUnitの例

junit_deps.png

JUnitはtestスコープで使用しているので、 hamcrestもtestスコープとなる。

2.3.2 Logbackの例

logback_deps.png

2.4 <dependency>の要素

<dependecy>には依存するアーティファクトの情報を記載します。

要素 説明
groupId グループ一意に特定するID org.springframework
artifactId グループ内で成果物を一意に特定するID spring-webmvc
version バージョン 4.2.4.RELEASE
scope その依存ライブラリをどの場面で使用するか(後述) compile

2.5 versionの考え方

PJ内で、ライブラリを共有する場合を考えてみます。

2.5.1 バージョン管理システムで共有する場合

svnを使用しているとします。

lib-svn.png

アプリ開発チームが、朝一番でsvn updateすると、PJライブラリに大幅に変更が入っていました。 アプリ開発チームは、新機能作成の途中で、変更されたライブラリの取り込みを余儀なくされました。

2.5.2 インハウスリポジトリで共有する場合

  • ライブラリ開発者は、バージョン番号をインクリメントして、ライブラリをインハウスリポジトリにデプロイします。
  • アプリ開発者は、pom.xmlの<dependency>の<version>を変更して、新しいライブラリを取得します。

lib-mvn.png

アプリ開発チームは、任意のタイミングでバージョンアップを行えます。

  1. 注意点

    SNAPSHOTバージョンを使用すると、最新のライブラリがダウンロードされるので、 バージョン管理システムで共有する場合と同じ事象が発生します。 明示的にバージョン番号を変更することで、任意のタイミングでライブラリを リリース/取り込みできます。

3 スコープ

3.1 スコープの種類

あるdependecyが、どのようなときに使用されるか(クラスパスに追加されるか)を 定義したものです。

スコープ 説明
compile コンパイル時に使用する
test テスト時に使用する
runtime 実行時に使用する
provided 実行時には、実行環境(コンテナ)により提供される

3.1.1 クラスパスが現れる場面

そもそも、クラスパスというものが、どのような場面で現れるのか おさらいしましょう。

場面 発行されるコマンド mvnでの例
コードをコンパイルする javac (src/main) mvn compile
テストコードをコンパイルする javac (src/test) mvn test-compile
アプリを実行する java (target/classes) mvn jetty:run
テストを実行する java (target/test-classes) mvn test

3.2 スコープとクラスパスの組み合わせ

上記の組み合わせをマトリックスにすると以下のようになります。

scope javac (src/main) javac (src/test) java (target/classes) java (target/test-classes)
compile o o o o
test x o x o
runtime x x o o
provided o o x x

3.3 TODO 小テスト

適切なスコープとその理由を考えてみよう。

ライブラリ 説明 適切なスコープ そのスコープにした理由
junit.jar ユニットテスト用ライブラリ    
ojdbc6.jar Oracle JDBCドライバ    
slf4j-api.jar ロギングライブラリ    
servlet-api.jar Servlet API    

4 Eclipseにインポートしてみよう

4.1 この章のねらい

  • pom.xmlとIDEがどう関連するかを学ぼう!

4.2 TODO MavenプロジェクトをEclipseに取り込んでみよう

File -> Import -> Existing Maven Project

eclipse-import.png

4.3 Mavenの設定がどうEclipseに取り込まれているか

Eclipseの設定を確認してみよう。

4.3.1 TODO Package Exploere

  • src/main/javaがソースフォルダとして認識されている
  • src/test/javaがソースフォルダとして認識されている
  • 依存ライブラリが追加されている(junit, hamcrest)

eclipse-explorer.png

4.3.2 TODO Project Properties (Source)

ソースフォルダ 出力先
src/main/java target/classes
src/test/java target/test-classes

eclipse-build-path-source.png

4.3.3 TODO Project Properties (Libraries)

  • 依存ライブラリJunitが、Mavenローカルリポジトリのjarを参照している

eclipse-build-path-libraries.png

4.3.4 TODO Project Properties (Resource)

  • Text file encoding が UTF-8 に設定されている

eclipse-resource.png

4.4 pom.xmlが変更された場合

pom.xmlが変更された場合、設定変更をEclipseに教えてあげる必要があります。

Maven -> Update Project...

4.4.1 TODO pom.xmlの変更を取り込んでみよう

pom.xmlを編集して、Eclipse上でUpdate Projectを実行してみましょう。

依存ライブラリを追加します。

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.2</version>
</dependency>

Update Projectを実行し、設定がどう変更したか確認します。

5 Mavenリポジトリ

5.1 この章のねらい

  • 各リポジトリの関係を理解しよう!
  • リポジトリ間の関係を理解しよう!

5.2 リポジトリの種類

Mavenで「リポジトリ」という場合、大きく2つに分類されます。

  • ローカルリポジトリ
  • リモートリポジトリ
種類 説明 主な用途
ローカルリポジトリ ローカルPC上にあるリポジトリ( ~/.m2/repository ) Mavenが直接参照する
リモートリポジトリ(インハウスリポジトリ)  PJ内で構築したリポジトリ PJ成果物(jar等)をPJ向けに公開する
リモートリポジトリ(公開リポジトリ) インターネット上に公開されたリポジトリ(Maven Central, jcenter等) ライブラリを公開する

repositories.png

5.3 ローカルリポジトリ

  • ファイルシステム上のキャッシュ(~/.m2/repository)。
  • mavenで使用するライブラリは必ずここにキャッシュされる。

retrieve-local-cache.png

5.4 インハウスリポジトリ

5.4.1 PJのライブラリをデプロイ・取得する

インハウスリポジトリを仲介して、ライブラリの配布を行うことができます。

retrieve-pj-lib.png

5.4.2 リモートリポジトリのファイルを取得する

インハウスリポジトリは、リモートリポジトリへのプロキシ、キャッシュを兼ねることが多いです。

retrieve-remote.png

インハウスリポジトリにキャッシュされている場合、リモートリポジトリへのアクセスは発生しません。

5.5 リモートリポジトリ

デフォルトではMaven Centralが有効なリモートリポジトリとして設定されている。

mvn help:effective-pom
<repositories>
  <repository>
    <snapshots>
      <enabled>false</enabled>
    </snapshots>
    <id>central</id>
    <name>Central Repository</name>
    <url>https://repo.maven.apache.org/maven2</url>
  </repository>
</repositories>

5.6 トラブルシューティング

5.6.1 依存関係が解決できない場合

  1. コマンドラインでupdateを指示する

    -Uオプションを使用することでリモートリポジトリに取得しにいきます。

    mvn -U compile
    
  2. ローカルリポジトリからアーティファクト(jar)を削除する

    ローカルリポジトリにjarがなければ、リモートリポジトリに取得しに行きます。

    rm ~/.m2/repository/junit/junit/3.8.1/*
    
  3. ローカルリポジトリに直接mvn installする

    明示的にローカルリポジトリにインストールしてしまえば、 依存関係の問題はさしあたり発生しません。

    mvn install:install-file -Dfile=<ファイル>
    
    # jarとpomをダウンロードする
    wget https://repo.maven.apache.org/maven2/joda-time/joda-time/2.9.2/joda-time-2.9.2.jar
    wget https://repo.maven.apache.org/maven2/joda-time/joda-time/2.9.2/joda-time-2.9.2.pom
    
    # 手動でインストールする
    mvn install:install-file -Dfile=joda-time-2.9.2.jar -DpomFile=joda-time-2.9.2.pom
    
  4. ローカルリポジトリ上の_remote.repositoriesファイルを削除する。

    ローカルリポジトリにjarが存在するにもかかわらず、その取得元リモートリポジトリにアクセスできない場合、 エラーになるようです。

    [ERROR] Failed to execute goal on project my-app: Could not resolve dependencies for project nablarch.example:my-app:war:1.0.1: Failed to collect dependencies at his-library:jar:1.0.5: Failed to read artifact descriptor for his-library:jar:1.0.5: Could not find artifact his-bom:pom:1.0.4 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
    

    他の人のローカルリポジトリをまるごとコピーしたような場合に、 上記のようなエラーが出ることがあります。

    _remote.repositoriesというファイルには、そのアーティファクトをどこから取得したか という情報が記載されているようです。 このファイルを削除すると、エラーは解消します。

6 プロパティ

6.1 プロパティ

pom.xml内で、

${プロパティ名}

のように記述することで、指定したプロパティの値が展開されます。

6.2 Mavenプロジェクトプロパティ

Mavenがデフォルトで用意しているプロパティがあります。

プロパティ名 デフォルト値
project.build.directory target
project.build.outputDirectory target/classes
project.build.testOutputDirectory target/test-classes
project.compileSourceRoots src/main/java
project.testCompileSourceRoots src/test/java

6.2.1 TODO プロパティにどんな値が設定されているか表示してみよう。

# pom.xmlの内容を確認する
cd example/maven_props
less pom.xml

# 実行してプロパティを表示する。
mvn antrun:run

6.2.2 TODO その他のプロパティを表示してみよう

以下のプロパティを表示して、どのような値が設定されているか見てみよう。

  • project.basedir
  • project.name
  • project.version
  • project.build.finalName
  • project.artifactId
# pom.xmlの内容を確認する
cd example/maven_props
vi pom.xml

# 実行してプロパティを表示する。
mvn antrun:run

6.3 環境変数

env.<環境変数名>で任意の環境変数を取得できます。

例:JAVA_HOMEの場合

env.JAVA_HOME

6.3.1 TODO 環境変数PATHを表示させてみよう

# pom.xmlを編集する
cd example/maven_props
vi pom.xml
# 実行してプロパティを表示する。
mvn antrun:run

6.4 TODO ユーザ定義プロパティ

<properties>内に、以下のように記載することで、 任意のプロパティを設定できます。

<プロパティ名>プロパティ値</プロパティ名>
<project>
  :
  <properties>
    <my.prop>MY PROPERTY</my.prop>
  </properties>
  :
</project>

6.4.1 使用例

  1. ライブラリのバージョン番号
    <dependency> 
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
    </dependecy>
    
  2. ファイルパス
    <properties>
      <hoge.home>path/to/hoge</hoge.home>
    </properties>
    

6.4.2 TODO 自分で設定したプロパティを表示してみよう

<echo message="my.prop=${my.prop}"/>
# pom.xmlを編集する
vi pom.xml
# 実行してプロパティを表示する。
mvn antrun:run

7 フェーズとゴール

7.1 ライフサイクル、フェーズ、ゴール

Mavenのライフサイクルにはいくつかのフェーズがあり、 各フェーズは、いくつかのゴールと関連付けられています。

lifecycle.png

  • フェーズはイベントと考えるとわかりやすい(loadとかDOMContentLoadedとか)
  • ゴールはイベント発生時にコールバックされる処理
  • どのようなゴールが関連付けられているかはpomの設定による(例:mvn package)

7.2 ライフサイクル

7.2.1 cleanライフサイクル

フェーズ
pre-clearn
clearn
post-clean

7.2.2 defaultライフサイクル

フェーズ
validate
generate-sources
process-sources
generate-resources
process-resources
compile
process-classes
generate-test-sources
process-test-sources
generate-test-resources
process-test-resources
test-compile
test
prepare-package
package
pre-integration-test
integration-test
post-integration-test
verify
install
deploy

7.2.3 siteライフサイクル

フェーズ
pre-site
site
post-site
site-deploy

7.3 フェーズ

主要なフェーズを以下に示します。

フェーズ 役割
compile コンパイル
test テスト
package アーティファクト(jar/war)を作成
verify CheckStyle等を実行
install ローカルリポジトリにインストール
deploy リモートリポジトリにデプロイ

各フェーズに登録されたゴールが実行されることによってビルドが行われます。 ゴールはプラグインが提供します。

7.3.1 TODO フェーズに関連付けられるプラグインが変更されることを確認しよう

cd example/phase_and_goal
# まずmvn packageを実行してみる
mvn package

# pom.xmlの<packaging>jar</packaging>をwarに変更する
vi pom.xml

# もう一度mvn packageを実行してみる
mvn package
フェーズ <packaging>jar</packaging> <packaging>war</packaging>
compile compiler:comile compile:compile
test surefire:test surefire:test
package jar:jar war:war

7.3.2 TODO 明示的にフェーズを変更してみよう

# mvn verifyを実行する
cd example/plugin
mvn -f pom-checkstyle.xml clean verify

# プラグインを実行するフェーズを変更する。
# 旧: <phase>verify</phase>
# 新: <phase>validate</phase>
vi pom-checkstyle.xml

# mvn verifyを実行する
mvn -f pom-checkstyle.xml clean verify

CheckStyleが実行されるタイミングに変化がありましたか?

8 プラグイン

Mavenの機能の多くはプラグインにより提供されています。

機能 プラグイン
コンパイルする maven-complier-plugin
jarを作る maven-jar-plugin

そのため、Mavenの動作をカスタマイズしたいときは、 <plugins>セクション内を編集することが多いです。

8.1 TODO 新たにプラグインを追加してみよう

CheckStyleプラグインを導入してみよう。

<plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-checkstyle-plugin</artifactId>
   <version>2.17</version>
   <executions>
     <execution>
       <id>checkstyle</id>
       <phase>verify</phase>
       <goals>
         <goal>checkstyle</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
# pom.xmlにプラグインの記述を追記する
vi pom.xml

# ゴールを直接指定して実行
mvn checkstyle:check  # mvn -f pom-cs.xml でもOK
[INFO] --- maven-checkstyle-plugin:2.17:check (default-cli) @ plugin ---
[INFO] There are 12 errors reported by Checkstyle 6.11.2 with sun_checks.xml ruleset.
[ERROR] src\main\java\com\example\App.java:[0] (javadoc) JavadocPackage: package-info.javaファイルがありません。
[ERROR] src\main\java\com\example\App.java:[0] (misc) NewlineAtEndOfFile: ファイルが新しい行で終了していません。
[ERROR] src\main\java\com\example\App.java:[7] (regexp) RegexpSingleline: Line has trailing spaces.
[ERROR] src\main\java\com\example\App.java:[7,1] (design) HideUtilityClassConstructor: ユーティリティクラスは、パブリックまたはデフォルトコンストラクタを持つべきではありません。
[ERROR] src\main\java\com\example\App.java:[8,1] (blocks) LeftCurly: '{' 列に 1 前の行にする必要があります。
[ERROR] src\main\java\com\example\App.java:[9,5] (javadoc) JavadocMethod: Javadoc コメントがありません。
[ERROR] src\main\java\com\example\App.java:[9,29] (whitespace) ParenPad: '(' の後にホワイトスペースがあります。
[ERROR] src\main\java\com\example\App.java:[9,30] (misc) FinalParameters: パラメータargs最終的にする必要があります。
[ERROR] src\main\java\com\example\App.java:[9,43] (whitespace) ParenPad: ')' の前にホワイトスペースがあります。
[ERROR] src\main\java\com\example\App.java:[10,5] (blocks) LeftCurly: '{' 列に 5 前の行にする必要があります。
[ERROR] src\main\java\com\example\App.java:[11,28] (whitespace) ParenPad: '(' の後にホワイトスペースがあります。
[ERROR] src\main\java\com\example\App.java:[11,43] (whitespace) ParenPad: ')' の前にホワイトスペースがあります。
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

フェーズを指定して実行してみよう。

# フェーズを指定して実行
mvn clean install

# checkstyle結果を確認
less target/checkstyle-result.xml

8.1.1 TODO 小テスト

どうして、mvn installしたらCheckStyleも実行されたのだろうか?

8.2 TODO 既存のプラグインの設定を変更してみよう

8.2.1 コンパイラの設定を変更する

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <java.version>1.8</java.version>
</properties>

<build>
  <plugins>
    <!-- ここにプラグインの記述を記載します -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.5.1</version>
      <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
      </configuration>
    </plugin>
  </plugins>
</build>
vi pom.xml
mvn compile  # mvn -f pom-java8.xml でもOK

# classファイルの中身を確認する
javap -v target/classes/com/example/App.class
  Last modified 2016/02/15; size 537 bytes
  MD5 checksum b675c50db7181ec07a659cfe45c5d67f
  Compiled from "App.java"
public class com.example.App
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
minor version Javaのバージョン
49 1.5
50 1.6
51 1.7
52 1.8

0x50=Java1.6だけは覚えておくとよい。

9 pomの継承

9.1 pomの継承

pom.xmlは親pom.xmlを持つことができ、親pom.xmlの情報を引き継ぐことができます。 子のpom.xmlは親からの差分を記述します。

9.1.1 何のためか?

モジュールが増えてくると、それぞれのpom.xmlに重複が発生するようになります。 複数のモジュール間で共通の設定を使用したい場合に使用します。

  • 共通のプロパティを使用したい(ファイルパス、ファイルエンコーディング等)
  • 使用するプラグインのバージョンを揃えたい
  • プラグインの設定を共通化したい(CheckStyle, FindBugs等)

9.2 デフォルトのSuper pom

pom.xmlにはデフォルトの親pom.xmlがあります。

http://maven.apache.org/ref/3.3.9/maven-model-builder/super-pom.html

9.3 継承する方法

継承するpom.xmlを<parent>に記載します。

ファイルシステム上、近い場所に配置されている場合、 pom.xmlへの相対パスを記述できます(relativePath)。 デフォルトは一つ上のディレクトリになります。

<parent>
  <groupId>グループID</groupId>
  <artifactId>アーティファクトID</artifactId>
  <version>バージョン</version>
  <!-- 兄弟ディレクトリを参照 -->
  <relativePath>../parent/</relativePath>
</parent>

そうでない場合、すなわちローカルリポジトリまたはリモートリポジトリに登録されたpom.xmlを 継承する場合は<relativePath>の中身を空にします。

http://central.maven.org/maven2/org/sonatype/oss/oss-parent/9/oss-parent-9.pom

<parent>
 <groupId>org.sonatype.oss</groupId>
  <artifactId>oss-parent</artifactId>
  <version>9</version>
 <relativePath/>
</parent>

9.4 TODO 親pomを継承してみよう

# 親pomの内容を確認する
cd example/parent_pom/my-parent/
less pom.xml

# 依存関係を表示する
mvn dependency:tree

親pomの依存関係には何も表示されません。

  • <dependencies> 依存関係に含める
  • <dependencyManagement> 定義のみ(子で利用する)
# 子pom
cd ../my-lib/
# 修正前の依存関係を表示する
mvn dependency:tree
# ファイルを編集して<parent>を追加する
vi pom.xml
<!-- 親pomを指定する -->
<parent>
  <groupId>com.example</groupId>
  <artifactId>my-parent</artifactId>
  <version>1.0.0</version>
  <relativePath>../my-parent</relativePath>
</parent>

<!-- <groupId>, <version>は親pomから引き継ぐ -->
<artifactId>my-lib</artifactId>
<packaging>jar</packaging>

<!-- versionは親pomの<dependencyManagement>から引き継ぐ-->
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

<groupId>と<version>は親pom.xmlから引き継がれます。

# 修正後の依存関係を表示する
mvn dependency:tree

9.5 TODO 親pomの設定を変更してみよう

cd example/parent_pom/my-parent
vi pom.xml

<verion>を4.12にしてみる。

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.12</version>
</dependency>
cd ../my-lib
# 依存関係を表示する
mvn dependency:tree

10 マルチモジュール構成

10.1 複数のモジュールを集約する(aggregate)

<modules>タグを使うことで複数のMavenモジュールを集約することができます。

集約しているモジュールに対してmavenコマンドを実行すると、 集約されているモジュール全てにそのコマンドが実行されます。

その際、モジュール間の依存関係に沿って順番にビルドが実行されます。

10.2 複数のモジュールを集約してみよう

10.2.1 TODO 個別のモジュールをビルドしてみよう

cd example/mulit_module/my-batch
# 中身を確認
less pom.xml

# コンパイルしてみる
mvn compile
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building my-batch 1.0.1
[INFO] ------------------------------------------------------------------------
Downloading: https://repo.maven.apache.org/maven2/com/example/my-lib/1.0.1/my-lib-1.0.1.pom
[WARNING] The POM for com.example:my-lib:jar:1.0.1 is missing, no dependency information available
Downloading: https://repo.maven.apache.org/maven2/com/example/my-lib/1.0.1/my-lib-1.0.1.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.875 s
[INFO] Finished at: 2016-03-21T09:44:40+09:00
[INFO] Final Memory: 9M/155M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project my-batch: Could not resolve dependencies for project com.example:my-batch:jar:1.0.1: Could not find artifact com.example:my-lib:jar:1.0.1 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
  • コンパイルに必要な依存ライブラリmy-libをローカルリポジトリに探しに行く
  • my-lib:1.0.1はまだmvn installされていない
  • Mavenセントラルリポジトリからダウンロードしようとする
  • ダウンロードできない(見つからない)のでビルドは失敗する

10.2.2 TODO 集約してみる

# pom.xml
cd example/multi_module
vi pom.xml
<modules>
  <module>my-batch</module>
  <module>my-lib</module>
  <module>my-web</module>
</modules>
mvn install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] my-lib
[INFO] my-batch
[INFO] my-web
[INFO] my-aggregate
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------

11 プロファイル

11.1 この章のねらい

  • mavenの「プロファイル」が何者か概要を理解しよう
  • プロファイルの切替ができるようにしよう
  • どのプロファイルが有効であるか調べられるようにしよう

11.2 プロファイルとは

プロファイルとは、かんたんにいうと、pom.xml内のif文です。

典型的には、リリース環境のちがいによってビルドの設定を変える用途に使います。 (テスト環境用にはこういうビルドをする、本番用環境用にはこういうビルドをする)

11.3 プロファイルの定義方法

pom.xml内で、

<profiles>
  <profile>
    <id>foo</id>
    <!-- ここに何か書く -->
  </profile>
</profiles>

のように記述することで、fooという名前のプロファイルが作成できます。

コマンド実行時に、-Pオプションを付けるとプロファイルの有効/無効を切り替えることができます。 上記の例だと、fooプロファイルが有効な時だけ、<profile>タグ内の設定が有効になります。

11.4 プロファイルの有効化・無効化

プロファイルの有効化・無効化をしてみよう

11.4.1 TODO pom.xmlを内容を確認します。

cd example/profile/
less pom.xml
<profiles>
  <profile>
    <id>en</id>
    <properties>
      <greeting.message>Hello!</greeting.message>
    </properties>
  </profile>
  <profile>
    <id>ja</id>
    <properties>
      <greeting.message>こんにちは!</greeting.message>
    </properties>
  </profile>
</profiles>
  • enとjaというプロファイルが定義されています。
  • enというプロファイルはデフォルトで有効になっています。

11.4.2 TODO プロファイルをenを有効にする。

mvn -P morning antrun:run

メッセージが表示されます。

[INFO] --- maven-antrun-plugin:1.3:run (default-cli) @ profile-test ---
[INFO] Executing tasks
     [echo] Hello!
[INFO] Executed tasks

11.4.3 TODO プロファイルjaを有効にする。

mvn -P jar antrun:run

11.4.4 TODO プロファイル指定なしで実行する。

mvn antrun:run
[INFO] --- maven-antrun-plugin:1.3:run (default-cli) @ profile-test ---
[INFO] Executing tasks
     [echo] ${greeting.message}
[INFO] Executed tasks

プロパティgreeting.messageが設定されなくなったので、プロパティがそのまま表示されてしまいました。

11.4.5 TODO デフォルトで有効なプロファイルを設定する

ほぼ毎回、有効にしているプロファイルがある場合、 そのプロファイルをデフォルトで有効になるよう設定できます。

<profiles>
  <profile>
    <id>en</id>
    <!-- このプロファイルをデフォルト有効にする。-->
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <greeting.message>Hello!</greeting.message>
    </properties>
  </profile>
mvn antrun:run

デフォルトでプロファイルenが有効になりました。

[INFO] --- maven-antrun-plugin:1.3:run (default-cli) @ profile-test ---
[INFO] Executing tasks
     [echo] Hello!
[INFO] Executed tasks

11.4.6 TODO プロファイルを無効にする。

デフォルトでenが有効になっているので、これを無効にして、jaを有効にします。

mvn -P-en,ja antrun:run
[INFO] --- maven-antrun-plugin:1.3:run (default-cli) @ profile-test ---
[INFO] Executing tasks
     [echo] こんにちは!
[INFO] Executed tasks

11.5 どのプロファイルが有効かを確認する

11.5.1 TODO mvn helpで確認してみましょう。

mvn help:all-profiles
[INFO] --- maven-help-plugin:2.2:all-profiles (default-cli) @ profile-test ---
[INFO] Listing Profiles for Project: com.example:profile-test:jar:1.0.0
  Profile Id: en (Active: true , Source: pom)
  Profile Id: ja (Active: false , Source: pom)

11.5.2 TODO プロファイルを切り替えてmvn helpを実行してみましょう。

mvn -P-en,ja help:all-profiles

どう変化しましたか?

12 ライセンス

Creative Commons Attribution 4.0 International (CC BY 4.0) とします。

https://creativecommons.org/licenses/by/4.0/

Created: 2016-06-03 金 14:39

Validate