jiichan.com

PROGRAMMING

Java
javascript
CSS
PHP

IntelliJ.Gradle.JavaFX (2) すべての依存対象を含んだ Fatjar を作る

前回の「アプリケーションを作る」 で出来た配布用のzipは、javafxなど依存ライブラリも含んでいるが、 exe化やインストーラー作成のことを考えた場合 Fatjar が良い。
そこで、すべての依存対象を含んだ Fatjar を作ってみる。
javafx以外の依存ライブラリとしては「QRコード生成」ライブラリを使う。

開発環境
IntelliJ IDEA 2021.2.2 (Community Edition)
jdk-15.0.1
javafx-sdk-15.0.1

依存ライブラリ(QRコード生成)を使用して作成したアプリ

テキストボックスに入力した URL を QRコードに替える。
ボタンクリックで QRコードが表示される。

Fatjar の作り方

実行可能jarに依存モジュール等を含める方法は、どうやら2通りあるらしい。

方法1:plugin(shadow)を使う方法
plugins {
    ..........
    ..........
    id 'com.github.johnrengelman.shadow' version '7.1.0'
}

dependencies {
    // QRコード生成(1次元・2次元コード画像処理ライブラリ)
    implementation 'com.google.zxing:core:3.4.1'
    implementation 'com.google.zxing:javase:3.4.1'
}

方法2:jarタスクを使う方法
jar {
    // ファイル重複のエラーが出ることがあるので回避のために下記一行を記載
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE

    // jar内に作成されるMANIFEST.MFのMainクラスを指定(これで実行可能jarとなる)
    manifest {
        attributes 'Main-Class': 'com.jiichan.demoshadow.Launcher'
    }
    
    // jarに依存ライブラリ(dependenciesで指定したモジュール等)を含める
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

dependencies {
    // QRコード生成(1次元・2次元コード画像処理ライブラリ)
    implementation 'com.google.zxing:core:3.4.1'
    implementation 'com.google.zxing:javase:3.4.1'
}

方法1:plugin(shadow)を試す

新規プロジェクトdemoShadowで試してみる。
この方法だと plugin に一行加えるだけなので簡単でよい。

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.10'
    // version 6 だとプロパティ'mainClassName'に値が指定されていませんとなる
    // verdion 7 以上で改善されているようだ
    id 'com.github.johnrengelman.shadow' version '7.1.0'
}

pluginに 'com.github.johnrengelman.shadow' version '7.1.0' を一行加えてbuild.gradleを更新してみた。
すると右サイドのGradleツールのTasksの中にshadowができていた。
そしてshadowの配下に、実行可能jarができそうな名前のshadowJarがあった。


早速shadowJarをクリックしてみた。
build/libsにFatjarであるdemoShadow-1.0-all.jarができていた。


ターミナルで実行してみると

> java -jar build\libs\demoShadow-1.0-all.jar
エラー: JavaFXランタイム・コンポーネントが不足しており、このアプリケーションの実行に必要です

とエラーになった。しかし javaFX のモジュールを含めた jar の起動方法が分からない。

そこで試行錯誤のうえ --add-modules で JavaFX を加えてみた。

> java --module-path C:\Java\javafx-sdk-15.0.1\lib --add-modules javafx.controls,javafx.fxml -jar build\libs\demoShadow-1.0-all.jar
    

すると問題なくアプリが立ち上がった。
こういう時は liberica jdk のように javaFX が同梱されたjdkがありがたい。

方法2:jarタスクを使う方法

テスト用に新規プロジェクトdemoFatjarを作って試してみた。
IntelliJで自動生成されたbuild.gradleにjar{}を追加。

jar {
    // ファイル重複のエラーが出ることがあるので回避のために下記一行を記載
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    // jar内に作成されるMANIFEST.MFのMainクラスを指定(これで実行可能jarとなる)
    manifest {
        attributes 'Main-Class': 'com.jiichan.demofatjar.Launcher'
    }
    // jarに依存ライブラリ(dependenciesで指定したモジュール等)を含める
    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

GraidleツールバーでTasks→build→build してみると


libsフォルダにFatjarが、さらにdistributionsフォルダもできてtarやzip作られていた。
このdemoFatjar-1.0.jarの場合も、方法1shadowのようにjavafxモジュールを--add-modulesして問題なく立ち上がった。

※ build.gradleで、パッケージ名に大文字が含まれると、 次のようにメインクラスが見つからない等の エラーがでるので注意。パッケージ名com.jiichan.demoFatjar.に大文字Fが含まれていた。

> java -jar build\libs\demoFatjar-1.0.jar
    エラー: メイン・クラスcom.jiichan.demoFatjar.HelloApplicationを検出およびロードできませんでした

まとめ1:
build.gradleのdependencies{}にjavaFxを記載しなくても、 FatjarにはjavaFxプラグインorg.openjfx.javafxplugin によってjavaFXが使えるようになるらしい。

まとめ2:
Fatjar作成にはshadowが簡単で良い。 plubin{}に一行加えてshadowJarするだけで生成される。


IntelliJ.Gradle.JavaFX (3) plugin Jlink でカスタム JRE を作る