Reputation: 1343
I can't seem to generate a cross-platform build out of a javaFX application.
When I run it from IntelliJ it works fine, and if package it through maven, I can also run the generated jar on Linux.
The problem occurs when I try to run the jar on Mac, where it seems that the JavaFX libraries are not included, then I get this stacktrace:
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 com.sun.javafx.tk.quantum.QuantumRenderer.getInstance(QuantumRenderer.java:280)
at com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:244)
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:261)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.RuntimeException: Error initializing QuantumRenderer: no suitable pipeline found
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:94)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
... 1 more
Exception in thread “main” java.lang.RuntimeException: No toolkit found
at com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:273)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
at com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
at com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
I am using Java 15 compiling to 11 and JavaFX11.
I'm also using maven profiles to generate a specific version every time, and the shade plugin to pack all the dependencies in one fat jar.
There's also a launcher, that's where the manifest points to, before the actual FX Application. This is how the pom looks like.
<profiles>
<profile>
<id>linux</id>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
</dependencies>
</profile>
<profile>
<id>mac</id>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>mac</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>mac</classifier>
</dependency>
</dependencies>
</profile>
<profile>
<id>win</id>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>org.log.Launcher</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I also noticed that no matter what profile I chose, it always generates the linux version, and I can see this maven log:
[WARNING] javafx-controls-11-win.jar, javafx-graphics-11-linux.jar, javafx-fxml-11-linux.jar, LogAnalyzer-1.0-SNAPSHOT.jar, javafx-base-11-linux.jar, javafx-controls-11-linux.jar, javafx-fxml-11-win.jar define 1 overlapping classes:
[WARNING] - module-info
[WARNING] javafx-controls-11-win.jar, javafx-controls-11-linux.jar define 1216 overlapping classes:
[WARNING] - com.sun.javafx.scene.control.TableColumnBaseHelper$TableColumnBaseAccessor
[WARNING] - javafx.scene.control.ComboBoxBase
[WARNING] - javafx.scene.control.skin.ColorPickerSkin$StyleableProperties$2
[WARNING] - com.sun.javafx.scene.control.inputmap.InputMap$KeyMappingInterceptor
[WARNING] - javafx.scene.control.cell.ChoiceBoxTreeTableCell
[WARNING] - javafx.scene.control.TableCell$3
[WARNING] - javafx.scene.control.skin.ProgressBarSkin$StyleableProperties$1
[WARNING] - javafx.scene.control.DialogPane$2
[WARNING] - javafx.scene.control.skin.ToolBarSkin$4
[WARNING] - javafx.scene.control.skin.ColorPickerSkin$3
[WARNING] - 1206 more...
[WARNING] javafx-fxml-11-linux.jar, javafx-fxml-11-win.jar define 80 overlapping classes:
[WARNING] - com.sun.javafx.fxml.expression.ExpressionValue$KeyPathMonitor
[WARNING] - javafx.fxml.FXMLLoader$RootElement
[WARNING] - com.sun.javafx.fxml.expression.Expression$Parser$TokenType
[WARNING] - javafx.fxml.FXMLLoader$DefineElement
[WARNING] - javafx.fxml.Initializable
[WARNING] - javafx.fxml.FXMLLoader$ControllerMethodEventHandler
[WARNING] - com.sun.javafx.fxml.BeanAdapter
[WARNING] - javafx.fxml.FXMLLoader$ControllerAccessor$1
[WARNING] - javafx.fxml.JavaFXBuilderFactory$ObjectBuilderWrapper$ObjectBuilder
[WARNING] - javafx.fxml.FXML
[WARNING] - 70 more...
[WARNING] maven-shade-plugin has detected that some class files are
[WARNING] present in two or more JARs. When this happens, only one
[WARNING] single version of the class is copied to the uber jar.
[WARNING] Usually this is not harmful and you can skip these warnings,
[WARNING] otherwise try to manually exclude artifacts based on
[WARNING] mvn dependency:tree -Ddetail=true and the above output.
[WARNING] See http://maven.apache.org/plugins/maven-shade-plugin/
I've been reading other posts and checking a few videos, and this seems to be happening to other people too, but looks a bit strange to me. What's also weird is that when I generate for windows, I don't see any .dll files inside the generated jar.
Does anyone know how to generate a FX cross-platform jar?
-------- EDIT --------
As suggested in other posts, I have a Launcher class, which calls the actual class that extends Application:
public class Launcher {
public static void main(String[] args) {
App.main(args);
}
}
And the JavaFX class:
public class App extends Application {
public static void main(String[] args) {
Application.launch();
}
@Override
public void start(Stage stage) throws IOException {
...
}
}
I now removed the profiles from the pom, so when compiling, maven should take all the dependencies (mac, linux and win), but still seems like it's only generating the linux dependencies (I'm running on linux, I guess this has something to do with it), because if I open the jar file, I don't see any .dll files and it still doesn't work on mac. Here is my full pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.log</groupId>
<artifactId>LogAnalyzer</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>mac</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>mac</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>org.log.Launcher</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Upvotes: 7
Views: 2614
Reputation: 1343
As suggested in one of the links provided in a comment by @jewelsea, the trick was to add explicitly the graphics module of each platform independently.
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
<classifier>win</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
<classifier>linux</classifier>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11</version>
<classifier>mac</classifier>
</dependency>
</dependencies>
It generates a fat jar and I can finally see the .dll files inside. Tried on linux and mac and it works on both platforms.
Upvotes: 9
Reputation: 38132
AFAIK it's not possible anymore to create a cross-platform JAR for JavaFX applications.
It should be possible to create platform specific JARs however.
I'm not very familiar with the Shade Plugin, but according to the docs it should be possible to exclude dependencies.
So e.g. for the mac version make sure you exclude all non-mac javafx dependencies.
Upvotes: 0