Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Mavenの真実とウソ

8,066 views

Published on

JJUG CCC 2019 fall g3のセッション資料です。

「ちょっと凝ったことをしようとすると大量のXMLを書かなきゃいけない」「プラグインを並べてもうまく動いてくれない」など、Mavenは誤解され敬遠され、Gradleなどの他のビルドツールにシェアを奪われてきました。

が、依然としてMavenはJavaのデファクトスタンダードなビルドツールに位置づけられており、マスターする価値は十分にあります。そして良く学んでみると、そもそもXMLで過度なカスタマイズしようというのが誤った使い方だったのに気づきます。そこへ至るにも、タスクランナーの延長線上にある他のビルドツールと異なり、Maven独特なライフサイクルとプラグインの関係性もきちんと理解しておかなければなりません。

Published in: Software
  • Login to see the comments

Mavenの真実とウソ

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

×