JavaFXアプリケーションをMavenプロジェクトで作り直す
前回作成したパスワード管理ツールをMavenプロジェクトで作り直し、jarファイルを作成するところまでを行います。
なお、今回からスペックの関係上OSがUbuntuになってますが、基本的な手順は変わらないはずです。
環境
- Ubuntu 20.04
- vscode
- JDK11
プロジェクト作成
mvn archetype:generate コマンドでプロジェクトを作成します。
入力ウィザードで以下を求められるので適当に入力します。
- groupId
- artifactId
- version
- package
mvn archetype:generate
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< org.apache.maven:standalone-pom >-------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:3.2.1:generate (default-cli) > generate-sources @ standalone-pom >>>
(省略)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 1854:
Choose org.apache.maven.archetypes:maven-archetype-quickstart version:
1: 1.0-alpha-1
2: 1.0-alpha-2
3: 1.0-alpha-3
4: 1.0-alpha-4
5: 1.0
6: 1.1
7: 1.3
8: 1.4
Choose a number: 8:
Define value for property 'groupId': com.swapps
Define value for property 'artifactId': PasswordManager
Define value for property 'version' 1.0-SNAPSHOT: :
Define value for property 'package' com.swapps: :
Confirm properties configuration:
groupId: com.swapps
artifactId: PasswordManager
version: 1.0-SNAPSHOT
package: com.swapps
Y: : Y
(省略)
ビルド設定
プロジェクトを実行するための設定をpom.xmlに記載します。
実行するための設定
以下を build -> plugins へ exec-maven-pluginを有効にする設定を追加します。これにより mvn exec:java で実行することができます。
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.swapps.App</mainClass>
</configuration>
</plugin>
パッケージングの設定
maven-assembly-plugin と maven-dependency-plugin を追加します。これにより mvn package を実行したときに jar ファイルが出力されるようになります。
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.swapps.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId></artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- configure the plugin here -->
</configuration>
</execution>
</executions>
</plugin>
ライブラリを追加
このアプリケーションで使用するライブラリを dependencies へ追加します。
- jackson-databind
- javafx-controls
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>18-ea+9</version>
</dependency>
実装
実装に関しては以下のソースコードをコピーして、App.java の package以下に貼り付け、データファイルのパスだけ同階層のディレクトリから読み込むように変更しました。
https://www.s-watanabe.work/2022/01/windowsjavafx.html#toc_headline_11Files.readAllLines(Paths.get("./data.json"))
動作確認
ターミナルを開いて mvn exec:java コマンドを実行すればアプリケーションを実行できます。
jarファイル作成
mvn clean package コマンドでビルドすることにより、targetディレクトリ下に jarファイルが生成されます。
$ mvn clean package
(省略)
[INFO] Building jar: ./PasswordManager/target/PasswordManager-0.1.jar
(省略)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
jarファイル動作確認
jarファイルを実行
ここで少しハマりました。単純にjarファイルを実行しようとすると以下のエラーが発生します。
$ java -jar PasswordManager-0.1.jar
エラー: JavaFXランタイム・コンポーネントが不足しており、このアプリケーションの実行に必要です
どうやら生成したjarファイルの中に openjfx のライブラリは含まれず、これはjarファイル実行時に別で読み込む必要があるらしいです。
確かに mvn clean package を実行したときに以下の警告が発生していました。
[INFO] --- maven-assembly-plugin:3.1.1:single (make-assembly) @ PasswordManager ---
[WARNING] Failed to build parent project for org.openjfx:javafx-controls:jar:18-ea+9
[WARNING] Failed to build parent project for org.openjfx:javafx-controls:jar:18-ea+9
[WARNING] Failed to build parent project for org.openjfx:javafx-graphics:jar:18-ea+9
[WARNING] Failed to build parent project for org.openjfx:javafx-graphics:jar:18-ea+9
[WARNING] Failed to build parent project for org.openjfx:javafx-base:jar:18-ea+9
[WARNING] Failed to build parent project for org.openjfx:javafx-base:jar:18-ea+9
[WARNING] Artifact: PasswordManager:jar:0.1 references the same file as the assembly destination file. Moving it to a temporary location for inclusion.
なぜ openjfx だけこのようになってしまうのかは調査中です。
軽視していましたが、このままでは実行できないので openjfx を別途導入します。
openjfxをインストール
apt-getでインストールします。
$ sudo apt-get install openjfx
インストールしたら dpkg コマンドで lib ディレクトリの位置を確認します。
dpkg -L openjfx
モジュールを指定して jarファイルを実行
java -jar -p /usr/share/openjfx/lib --add-modules javafx.controls PasswordManager-0.1.jar
- --module-path [-p] … 追加で読み込むモジュールのパス
- --add-modules … 追加で読み込むモジュール名
一応はこれで実行できました。
QuantumRendererが発生する場合
はじめ JavaFX公式ページ から、SDKをダウンロード/解凍し、中のライブラリを指定し試しましたが QuantumRendererエラーが発生しうまく行きませんでした。
$ java -jar -p javafx/lib --add-modules javafx.controls PasswordManager-0.1.jar
Graphics Device initialization failed for : es2, sw
Error initializing QuantumRenderer: no suitable pipeline found
java.lang.RuntimeException: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:283)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:254)
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:264)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:291)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:410)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:95)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
at java.base/java.lang.Thread.run(Thread.java:829)
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: No toolkit found
at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:276)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:291)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:163)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:659)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:410)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
... 5 more
コメント
コメントを投稿