起きたこと
Java8前提で作られいったものを、Java17で操作させるとはまる話。今回はJigsaw 関係なのかなぁ~
どちらにしてもまだ見ぬだれかの無駄時間を少しでも削るために、解決までの経緯と考えたことをいつものように開示します。
実行環境
No | 環境項目 | 備考 |
---|---|---|
1 | Java | openjdk 17 2021-09-14 |
2 | maven | Apache Maven 3.6.3 |
3 | swagger-editor | https://editor.swagger.io/ |
やったこと
- Swaggerファイルをローカル環境で作成
- codegen を実行 SpringBootコードを生成
that's all. 最初からつまずくのよね。
じゃぁさっそく
swagger-codegenは、swaggerファイルから、API接続クライアントとAPIサーバーのsutubを生成するプログラムです。
今回はswaggerファイル(sample.yml)を指定して、server-stubを作成します。普通に。公式の指定通りに。。
java -jar C:\dev\tools\codegen\swagger-codegen-cli-3.0.30.jar generate -i sampleapi.yml -l spring -o sample
6:48:31.014 [Thread-0] WARN i.s.c.v.i.CodegenIgnoreProcessor - Output directory does not exist, or is inaccessible. No file (.swagger-codegen-ignore) will be evaluated.
16:48:31.028 [Thread-0] WARN i.s.c.v.g.DefaultCodegenConfig - Empty operationId found for path: get /sample. Renamed to auto-generated operationId: sampleGet
16:48:31.033 [Thread-0] WARN i.s.c.v.g.DefaultCodegenConfig - Empty operationId found for path: post /sample. Renamed to auto-generated operationId: samplePost
Exception in thread "Thread-0" java.lang.RuntimeException: Could not generate api file for 'sample'
…
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.Collections$EmptyMap.isEmpty() accessible: module java.base does not "opens java.util" to unnamed module @fa49800
と、実行するわけですが。。
エラーです。なんでやねん!!!と思います。これが別の言語なら則、だれかに助けを求めたくなる程度には厳しい状況。なんせエラーの原因がわからない。でも。さすがそこはJava様(僕が慣れているだけかもですが)きっちりとヒントだけ残してくれます。今回注目すべき大ヒントはこれ
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make public boolean java.util.Collections$EmptyMap.isEmpty() accessible: module java.base does not "opens java.util" to unnamed module @fa49800
ここですわ。module @fa49800アクセスできないとか、地球は回っているとかなんとか。「module」あぁ、ピンときました。。Java9で導入されたあいつ。たしかProject Jigsawですね。はいはい。またJDKの仕様変更に起因したやつです。まぁ、この辺りではいろいろ変わっているのは仕方ないと踏んでいました。。さて調べてみましょう。ありました。JSR 376ですね。これによるとmodule-pathとclasspathでの参照に名前が設定されていないクラスを参照しているのが問題のようです。原因がわかれば、あとは回避策を確認するだけですね。公式(当時はoracleかな)のドキュメントを探します。こんなところかな。
ではこちらを参考に
java --add-opens=java.base/java.util=ALL-UNNAMED -jar C:\dev\tools\codegen\swagger-codegen-cli-3.0.30.jar generate -i sampleapi.yml -l spring -o sample
17:07:56.383 [Thread-0] WARN i.s.c.v.i.CodegenIgnoreProcessor - Output directory does not exist, or is inaccessible. No file (. writing file sample\src\main\java\io\swagger\configuration\LocalDateTimeConverter.java
…
17:07:56.641 [Thread-0] INFO i.s.codegen.v3.AbstractGenerator - writing file sample\.swagger-codegen\VERSION
はい。普通にとおりました。
まとめ
わたしも、プロジェクトで利用することなかったので、module関係を確認するいい機会になりました。何度か書いていますがJavaは新仕様と旧仕様を橋渡しする方策が手厚く考えられているので、module-pathを導入しても従来のclass-pathの仕掛けが利用可能なように配慮されています。これを前提に、調査することで、わりと短時間で問題を解決することが可能です。
参考資料