はじめに
今はまだ、勇気も自信も全然だから。これが精一杯、nikkieです。
JavaのMavenってあるじゃないですか。
触ることがあるんですが、「なんだかよくわからなくてイカツイな」「Pythonと結構違うんだよな」と感じてきました。
このたび「避けずに少し勉強する1」で小さく素振りしてみました。
※JavaやMavenは全然精通していないので、なにか間違えていたら@ftnextまでお知らせください!
目次
- はじめに
- 目次
- 動作環境
- 『プロになるJava』16章でMavenを完全に理解
- 2章のHello WorldをMavenでビルドして動かす
- 16章のbusinessCalendar4Jを使ったプログラムをMavenでビルドして動かす
- pom.xmlに宣言したバージョンを書き換えて、パッケージのバージョンアップ
- 終わりに
動作環境
ビルドしたjarファイルはどちらのjavaでも実行できることを確認しています
『プロになるJava』16章でMavenを完全に理解
- Mavenはビルドツール!
- pom.xml4で依存ライブラリ(dependency)を宣言する
- Goals
mvn test
とかmvn clean
とかmvn package
がGoal- 表16.2の整理がめちゃめちゃ分かりやすい!
- 「packageはtestを実行した上で...」、そういうことか!
- どれもtargetディレクトリを扱っていたのか!
2章のHello WorldをMavenでビルドして動かす
IntelliJ IDEAでは動かせているので、Mavenでビルドしたjarを動かしてみます
// src/main/java/projava/JapaneseHolidays2023.java package projava; public class JapaneseHolidays2023 { public static void main(String[] args) { System.out.println("Hello World"); } }
mvn package
でビルドしたJARを実行すると
(コマンドは <javaのフルパス> -jar target/projava-maven-practice-1.0-SNAPSHOT.jar
)
助けて〜、GPT-4えもん〜
maven-jar-plugin
GPT-4えもんの回答
mvn package コマンドを使って実行可能なjarファイルを生成するためには、プロジェクトの pom.xml ファイルに Maven の maven-jar-plugin を設定します。このプラグインを用いることで、jarファイルの生成時にマニフェストファイルを自動的に作成し、その中に 'Main-Class' 属性を設定することが可能です。
(※この後に設定例が続くのですが、省略します)
回答を参考に以下のように設定。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.3.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>projava.JapaneseHolidays2023</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build>
この設定により、Mavenでビルドしたjarを動かして「Hello World」の出力を得ました!
16章のbusinessCalendar4Jを使ったプログラムをMavenでビルドして動かす
サンプルコードが公開されています
書籍に沿ってpom.xmlにdependenciesを追加5
<dependencies> <dependency> <groupId>one.cafebabe</groupId> <artifactId>businessCalendar4j</artifactId> <version>1.21</version> </dependency> </dependencies>
実装(2022年を2023年に変えました)
mvn package
6でJARをビルド!
実行すると...
Exception in thread "main" java.lang.NoClassDefFoundError: one/cafebabe/bc4j/BusinessCalendar
再度の、助けて〜、GPT-4えもん〜
maven-assembly-plugin
GPT-4えもんの回答
エラーメッセージ "Exception in thread "main" java.lang.NoClassDefFoundError: one/cafebabe/bc4j/BusinessCalendar" は、JVM(Java Virtual Machine)が one.cafebabe.bc4j.BusinessCalendar クラスを見つけられなかったことを示しています。これは、依存関係のあるJAR(このケースではbusinessCalendar4J)がクラスパスに含まれていないために発生します。
そのため、あなたが作成したJARファイルが依存するJARを含んだ"Fat JAR"(または"Uber JAR"とも呼ばれます)を作成する必要があります。そのためには、Mavenのmaven-assembly-pluginを使用します。
(※この後に設定例が続くのですが、省略します)
Fat JARなるものを作っていきます7。
<build> <plugins> <!-- 省略 --> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.6.0</version> <configuration> <archive> <manifest> <mainClass>projava.JapaneseHolidays2023</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
mvn package
でビルドしたJARを実行。
<javaのフルパス> -jar target/projava-maven-practice-1.0-SNAPSHOT-jar-with-dependencies.jar
Holiday{date=2023-01-01, name='元日'} Holiday{date=2023-01-02, name='休日'} Holiday{date=2023-01-09, name='成人の日'} Holiday{date=2023-02-11, name='建国記念の日'} Holiday{date=2023-02-23, name='天皇誕生日'} Holiday{date=2023-03-21, name='春分の日'} Holiday{date=2023-04-29, name='昭和の日'} Holiday{date=2023-05-03, name='憲法記念日'} Holiday{date=2023-05-04, name='みどりの日'} Holiday{date=2023-05-05, name='こどもの日'} Holiday{date=2023-07-17, name='海の日'} Holiday{date=2023-08-11, name='山の日'} Holiday{date=2023-09-18, name='敬老の日'} Holiday{date=2023-09-23, name='秋分の日'} Holiday{date=2023-10-09, name='スポーツの日'} Holiday{date=2023-11-03, name='文化の日'} Holiday{date=2023-11-23, name='勤労感謝の日'}
動いた!!🙌
(祝日って17日しかないんだ...8)
pom.xmlに宣言したバージョンを書き換えて、パッケージのバージョンアップ
『プロになるJava』16章には以下のようにあります。
ライブラリのバージョンアップはversion要素を書き換えるだけで済みます。(Kindle版 p.636)
バージョンアップしてみましょう!
businessCalendar4Jは1.22や1.3.xがリリースされています。
https://search.maven.org/artifact/one.cafebabe/businessCalendar4j
最新まで上げてみたところ、1.3.xではAPIが破壊的に変更されたようでコンパイルできず。
今回は1.21 -> 1.22に上げてビルドしました。
<dependencies> <dependency> <groupId>one.cafebabe</groupId> <artifactId>businessCalendar4j</artifactId> - <version>1.21</version> + <version>1.22</version> </dependency> </dependencies>
pom.xmlの宣言を変えてビルド(mvn package
)というのは新鮮です〜
終わりに
Maven、完全に理解したかもしれない〜✌️
慣れ親しんだPythonのpipとは所作が結構違いますが、これはもう完全に別物として考えるのが私にはしっくり来ています。
ちょっとだけ触ったRust(Cargo)もMavenに近いかもな〜9
ありがとう、『プロになるJava』、そして、GPT-4えもん!
GPT-4えもんに今回はめっちゃ助けられましたし、「これってどうやるんだろう」と書籍からちょっと脱線するというムーブが成功したことに大満足です。
ちなみに、今回のプロンプト
あなたはJavaの開発経験が豊富なエンジニアです。新人開発者からの質問に根気よく丁寧に回答してください。 新人開発者「javaのjarファイルの実行について教えてください」
新人開発者「...」
でひたすら聞きまくりました(最後の方は面倒に感じて普通に聞いていた)
そして、Mavenを使った開発、ニジガク🌈要素あるよね!?
ときめいちゃった! ぽむー🎀
- こちらの「追伸」です ↩
- /opt/homebrew/Cellar/openjdk/20.0.1/libexec/openjdk.jdk/Contents/Home/bin/java↩
- ~/Library/Java/JavaVirtualMachines/openjdk-20.0.2/Contents/Home/bin/java↩
- あれ... もしかして... ぽむー🎀↩
- https://github.com/projava17/examples/blob/78c3d6822824b1338a3ea185b7921b846c41e9eb/part-5/chapter-16-build-tool/pom.xml#L16-L22↩
-
実際は
mvn clean package
でtargetディレクトリを消して(自分がハマりづらくして)からビルドしています↩ - mainClassの宣言はmaven-assembly-pluginでも行いました。maven-jar-pluginをコメントアウトしても動きます↩
-
数え間違えたかと思って
wc -l
しても17日でした。現実は非情である↩ - ↩