Mavenの真実とウソ
kawasima
#ccc_g3
JJUG CCC 2019 fall
Mavenに関する世間の印象
XMLを沢山かかなきゃいけない
既存のプラグインの組み合わせじゃやり
たいことができない。
主に使っているビルドツール2018
https://snyk.io/blog/jvm-ecosystem-report-2018-tools/
Javaビルドツールの歴史的な背景
2000年頃 2004年
依存管理をプラス
2004年
2007年
アンチテーゼ アンチテーゼ
XML Hell?
今どき(v3.6.2)、でこれだけ書いとけばOK
それでもXMLが嫌なら…
polyglot-mavenを使えば、YAMLでpom書くことができる
.mvn/extensions.xml に、これ書くだけ。
demo
polyglot-maven、Groovyで書くこともできちゃう…!
Gradle側から見たMaven
(Flexible)
https://gradle.org/maven-vs-gradle/
“GradleとMavenはどちらも、Convention
over Configurationを提供する。
ただMavenはカスタマイズが面倒でときには不
可能となる非常な厳格なモデルが用意されて
いる。これにより、特別な要件が無いのであ
ればビルドの理解が容易になりますが、多く
の自動化の問題に適さないことでしょう。”
柔軟性が無い?
Database Migrationを使ってテーブルを作る
用意したSQLファイルを実行して、テストデー
タを投入する。
作ったテーブル定義からマスタのEnumクラス
をジェネレートする。
プロセスをXMLで書くのは確かにしんどい…
だが、これはMaven-Wayではない!
flyway-maven-plugin
sql-maven-plugin
sql-maven-pluginでsrc/main/javaに出力する?
ってことはgenerate-sourcesフェーズで実行しないと…
例
Javaが少しでも書ける人ならば、
プラグインを作るのはとても簡単
異なるプラグインを組み合わせて、なんとか実現しよう
という発想をやめよう!
アドバイス
Gradle側から見たMaven
(Performance)
https://gradle.org/maven-vs-gradle/
Gradleの方が速いとしているが、一番時間のかかるテストの
フェーズで、mavenのsurefireプラグインのパラレルオプショ
ンが付けられていないのでフェアと言えなそう…
Mavenの基本構成
Plugin
Life cycle
Phase1
Phase2
Phase3
Phase4
Phase5
Goal A
Goal B
Plugin
Goal C
resourcesdefaultライフサイクル
process-resources
compile
test
package
install
resources
surefile
deploy
compiler
compile
test
jar
jar
install
install
deploy
deploy
デフォルトのライフサイクル
ライブラリのidentity
GroupId
ArtifactId
Version
世界で一意なグループの識別子
(いわゆるネームスペース)
グループの中で一意な識別子
バージョン
RELEASE
SNAPSHOT
※厳密にはpackagingとclassifierを加えて一意
SNAPSHOTの使い方
開発中はSNAPSHOTを使う
自チームのコントロール下にあるモ
ジュールを開発中にテストしたいと
きのみにSNAPSHOTを使う。
Icon made by Freepik from www.flaticon.com
リポジトリ
パッケージングされたライブラリ(Artifact)が
格納される場所
Local
Remote
ローカルのユーザ毎に格納される
デフォルトは$HOME/.m2/repository
ネットの向こう側に置いてみんなが使う
ビルトインなサブモジュール
サブモジュールの仕組みが標準なので、複数の
モジュールを簡単に扱える
Plexus Container
Sisu
Guice
Classworld Aether
DIの仕組み。コンフィグや
Maven自体のコンポーネントを
Mojoにインジェクションする。
ClassLoaderの
ロード順を変え
たり、なんだり
Dependencyを解決し、
Mavenリポジトリから
Artifactを取ってくる
Wagon
リモートからファイルを
取ってくるためのプロトコル
抽象レイヤ
MavenSession
RepositorySystemSessionMavenProject
LocalRepository
RemoteRepository
Maven
Lifecycle
Phase
Plugin(mojo) Mavenのしくみ
aetherを使えばこんなこともできる
https://github.com/kawasima/try-artifact
demo
よく使うプラグイン
標準プラグインでMustなもの
compiler
surefire
compiler
いわゆるjavacを実行するやつ。
コンパイラのバージョン指定に必須
デフォルトのJDKバージョン
3.8.0以降 1.6
3.8.0以前 1.5
いずれにせよ古い…
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>8</release>
</configuration>
</plugin>
JDK8以前
JDK8以降
surefire
MavenデフォルトのsurefireバージョンだとJunit5の
テストが認識されないなどの相性問題がよく起きる
ので、最新のものをバージョン指定する。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
知っておくと便利な標準プラグイン
dependency
assembly
dependency:purge-local-repository
「何か上手く依存ライブラリが更新されない」など
の問題にぶちあたったとき…
.m2/repositoryをゴッソリ消す
dependency:purge-local-repository を使って
そのプロジェクトの依存ライブラリを一度purgeする
dependency:analyze
使われていない依存ライブラリを検出する。
テストが無いのも一目瞭然
assembly
バッチなどで、シェルスクリプトなどをまとめて
アーカイブするときに使う
サードパーティ製おすすめプラグイン
frontend
versions
Jib
Github
frontend
nodeの環境がなくても、
自動的にインストールして、
npmやwebpack実行してくれる
elm用も作ってあります
versions
依存ライブラリのバージョン更新を調べたり、
プロジェクトのpom.xmlのバージョンを更新したり
versions
リリース作業は、maven-release-pluginを使うよりも
こっちを使った方が細やかでミスが少ない。(個人の感想)
% mvn versions:set -DremoveSnapshot=true
% mvn versions:revert
SNAPSHOTを外す
元に戻す
jib
Dockerイメージをシュッと作る
demo
GitHub
Maven siteをgh-pagesにプッシュする。GitHub製。
つかってみよう
Phaseに結び付けずに使う
ライフサイクルで動いてくれないので、
% mvn jib:dockerBuild
などのように、プラグイン名:ゴールを指定して動かす。
Phaseに結び付けて使う
Mavenのログ見るときに重宝する
ので一意で分かりやすい名前を
こうしておくと、mvn package実行すると、packageフェーズでこの
プライグインが自動的に動いてくれる
つくってみよう
ボイラープレート生成
アーキタイプでボイラープレート自動生成
% mvn archetype:generate 
-DarchetypeGroupId=org.apache.maven.archetypes 
-DarchetypeArtifactId=maven-archetype-plugin 
-DarchetypeVersion=1.4
プラグインの名前
[名前]-maven-plugin とする
こうしておけば、Mavenプラグインとアーティファクト名から一目瞭然だし、
実行時には[-maven-plugin]の部分を省略可能
% mvn プラグイン名:ゴール
maven-[名前]-plugin は、maven公式プラグイン用のネームスペースと
されているので注意!
example-maven-plugin/
├── pom.xml
└── src
├── it
│   ├── settings.xml
│   └── simple-it
│   ├── pom.xml
│   └── verify.groovy
├── main
│   └── java
│   └── [package]
│   └── MyMojo.java
└── test
├── java
│   └── [package]
│  └──MyMojoTest.java
└── resources
└── project-to-test
└── pom.xml
インテグレーションテスト用
プラグイン本体
ユニットテスト用
Mojo
maven pluginの1タスク。
引数なしのexecuteメソッドを実装するだけ
void execute() throws MojoExecutionException, MojoFailureException;
MojoFailureException: 予期する例外
プラグインの使い方が間違っている、前提条件を満たしてないなど、プラ
グインの利用者に伝えたいもの
MojoExecutionException: 予期しない例外
Mojoでハンドリングしないもの(ふつうはMojoからthrowする必要はない)
Mojoのクラスアノテーション
goalの名前
Executionsで実行フェーズを省略したときに
このゴールが実行されるフェーズ
設定値のインジェクション
引数で設定値を指定するときの名前
pomのconfigurationで設定値を指定するときの名前
executeの実装
プラグインのビルド、インストール
% mvn install
ふつうのMavenのプロジェクトと同じく、
mvn installするだけ。
テスト
Mojo単体でのテスト
JUnit使ってふつうに書く
プラグインを使うテスト用プロジェク
トを作って、プラグインを動かし、結
果をアサーションする
インテグレーションテスト
integration-test
もともとデフォルトのライフサイクルの1フェーズに存在する
AssertionはGroovyなどで書ける
verify.groovy
デプロイ
作ったプラグインをチームのリポジトリにデプロイすれば
チームみんなが使えるようになる
% mvn deploy
作ったプラグインを使う
実行する
% mvn install -Dmaven.test.skip=true
[WARNING]         ,、,,,、,,,
      _,,;' '" '' ;;,,
    (rヽ,;''""''゛゛;,  ノr)
    ,; i ___  、___iヽ゛;,    テストしないとかお前それ@t_wadaの前でも同じ事言えんの?
  ,;'''|ヽ・〉〈・ノ |゙ ';,
  ,;''"|    ▼    |゙゛';,
  ,;''  ヽ _人_ /  ,;'_
/シ、 ヽ ⌒⌒ /   リ \
|    "r,,`"'''゙´    ,,ミ|
|             リ、 ,    リ |
|    i   ゛r、ノ,,r" i _ |
|    ――`ー -----------┴ ´⌒ )
(ヽ _____________ ,, _´)
(_ _______________ ,,⌒ ィ
T |
| |
Centralデプロイ
作ったプラグインをCentralリポジトリにデプロイすれ
ば世界のみんなが使えるようになる
demo
プラグイン作例
EclipseLink static weave
開発動機:
EclipseLinkは、ビルドしたEntityクラスに対してWeavingという
バイナリ書き換えを行う。
このMavenプラグインは存在するが、persistence.xmlを必要とするので
無くてもWeavingする必要があった。
https://github.com/kawasima/staticweave-nopu-maven-plugin
DBAプラグイン
開発動機:
データベースのスキーマ(データ含む)のバージョンと、アプリケーションの
バージョンを同期をとりたい。
https://syobochim.hatenablog.com/entry/2015/12/12/232318
https://github.com/coastland/gsp-dba-maven-plugin
WAITT
開発動機:
Eclipseのtomcatプラグインのdependencies扱いまわりにバグが
あって、中々修正されないので、自前で開発した。
demo
サーバを選択し、Webアプリケー
ションを起動する
Webアプリケーションのカバレッジを取る
アプリケーションのダッシュボード
Springを使っていなくても、アクチュエイターみたいなのが付けれる
Executable jarを作る
seasar2でも、Strutsでも、struts1でもExecutable jarがア
プリケーションに何も手を加えず作れる!
そのほかご要望があれば作ります
まとめ
●
Mavenはプロジェクトの構成を書くもの。
プロセスを書きたければ、プラグインを作ろ
う。(簡単だよ)
●
作ったプラグインはCentralリポジトリにデ
プロイしてみよう!

Mavenの真実とウソ