ひらおかゆみのなげやりブログ

もう、なげやりです…

Java 9で作成したJavaFXアプリケーションをOpenJDK 11+OpenJFX 11用にアップデートする

このエントリは、Java Advent Calendar 2018じゃばえふえっくす Advent Calendar 2018の19日目です。そして今日12月19日はわたしの誕生日でもあります(年齢のことは聞かないお約束です)。さらに約1年ぶりのブログで、Javaに触れるのも1年ぶり、PCに触れるのも数か月ぶりくらいというお久しぶりです。JavaのAdvent Calendarからも以前お見かけした名前はなくなっていて、寒い時代になったと思いませんか?

さて、昨年のJavaFX Advent Calendar 2017では、一昨年にJava 8で作成したJavaFXアプリケーションをJava 9のモジュールに対応させてみました。 

blog.yumix.net

今年は、これをJava 11に対応させてみます。

Javaから約1年間遠ざかっていたので、世の中的にJava 10が存在したことも、Javaが有償化される?されない?で大騒ぎがあったこともよくわかりません。ただ、Java 11から、とても残念なことにJavaFXが削除されてしまいました。とても残念でなりませんが、OpenJFX単独でやっていくようなので、 断腸の思いでこれを受け止めることにします。

Java 11以降でJavaFXを使用するには、別途OpenJFXをインストールする必要があります。基本的な手順については、すでに櫻庭さんがブログでお書きになっています。

skrb.hatenablog.com

skrb.hatenablog.com

櫻庭さんのブログを拝見して、たぶんMavenを使うとOpenJFX SDKを直接インストールしなくてもよさそうなことはわかりました。それでもはっきり言って、敷居が上がっています。超面倒になっていますし、javapackagerもなくなっています。この件に関してはいろいろ言いたいことはありますが、そのままでは前に進めないので、公式ドキュメントを片手にとりあえず進めてみます。 

幸いなことに、昨年頑張ってJava 9のモジュール対応をやった甲斐があってか、 Javaのソースコード自体は変更する必要がありませんでした。修正はpom.xmlだけ、完成形を引用します。

pom.xml of Asteroid Viewer for OpenJFX 11

まず、依存関係に org.openjfx:javafx-controls:11 と org.openjfx:javafx-fxml:11 を指定します。これらがそれぞれモジュール javafx.controls と javafx.fxml に対応します。このほかのモジュールも同じような命名規則で登録されています。

続いて、Mavenプラグインを追加します。maven-compiler-pluginがコンパイルに使うもの、exec-maven-pluginが実行に使うものです。昨年maven-compiler-pluginのバージョンでいろいろあったので、念のため最新版の3.8.0にしました。それから、櫻庭さんのブログにもあるように、exec-maven-pluginを追加して mvn exec:java で実行しないとなぜか動かない仕様?なので、素直に従います。昨年版にはこれ以外に2つプラグインを使っていましたが、今回は出番がないので外しました。

これで動作するようにはなりましたが、「may not be accessible to clients due to missing 'requires transitive'」という警告が残っています。JavaFXのFXMLLoaderクラスとColorクラスを使用しているところのようです。原因がはっきりしないまま放置すると後々痛い目に遭うので、この時点で解決することにしました。

警告メッセージをそのままGoogle検索すると、それらしき情報が見つかります。

stackoverflow.com

とりあえず、module-info.javaでJavaFXのモジュールをインポートしている箇所の「requires」を「requires transitive」に置き換えると警告は出なくなります。これにはモジュールの依存関係が関係しているようで、javafx.controlsモジュールのJavadocを見ると、必要なモジュールjavafx.baseとjavafx.graphicsにそれぞれ「transitive」というModifierが付加されているのがわかります。最終的に解決できればプログラムは実行できますが、「transitive」な依存モジュールがある場合には、「requires transitive」としてあげないと警告が出るようです。Java 9の頃には「requires」で問題なかったため、Java 11でJavaFXが削除されたことで依存関係の定義が変わったのかもしれません。

今回、OpenJFX 11に移行してみてわかったことをまとめます。

  • JavaFXのアプリケーションはモジュール化しておいた方が楽です。JavaFXモジュールの依存関係がMavenの依存関係とほぼ1対1に対応しているので、pom.xmlでしているするときにわかりやすいです。
  • JavaFXアプリケーションのソースコードは基本的に修正する必要はありません。その代わり、pom.xmlは大きな書き換えが必要で、Java 8~9の頃にできたパッケージングも使えなくなり、制限事項はまだ多く残っています。
  • module-info.javaの「requires」と「requires transitive」の違いを意識する必要があるかもしれません。