openjdk-jfx
openjdk-jfx copied to clipboard
Include dependencies in jar
Hi
I'm trying to include all the (openjfx) dependencies in a fat jar so it can be run without OpenJFX installed. I have successfully built a .jar file contained all the dependencies (I think), but for whatever reason I get: Error: JavaFX runtime components are missing, and are required to run this application. I'm not sure if this is a bug or just a lack of knowledge. Either way, I think a working example could be useful.
pom.xml (copy HelloFX.java to src/)
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>HelloFX</groupId>
<artifactId>HelloFX</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>10</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>HelloFX</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>HelloFX</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11</version>
</dependency>
</dependencies>
</project>
$ mvn --version
Apache Maven 3.5.4 (NON-CANONICAL_2018-09-08T01:02:16+02:00_root; 2018-09-08T01:02:16+02:00)
Maven home: /opt/maven
Java version: 10.0.2, vendor: Oracle Corporation, runtime: /usr/lib/jvm/java-10-openjdk
Default locale: da_DK, platform encoding: UTF-8
OS name: "linux", version: "4.18.10-arch1-1-arch", arch: "amd64", family: "unix"
$ java --version
openjdk 10.0.2 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13)
OpenJDK 64-Bit Server VM (build 10.0.2+13, mixed mode)
So LauncherHelper.java abort as the module javafx.graphics isn't available and a single jar can only contain a single module (?).
So a self-contained .jar with OpenJFX seems to be unsupported at the moment?
I can try later to reproduce, but you are using Java 10, which includes JavaFX, and then adding JavaFX 11 dependencies. That looks like a bad idea.
The reason is that the Java 11 runtime will check if the main class extends javafx.application.Application, and if that is the case, it strongly requires the javafx platform to be available as a module, and not as a jar for example. It was discussed here: http://mail.openjdk.java.net/pipermail/openjfx-dev/2018-June/021977.html
While going modular is definitely the way to go, I still think it's unfortunate that JavaFX applications are treated a bit different here from other application (where you can still use the classpath).
There are some easy workarounds though. For example, you can have a main class that is not extending javafx.application.Application, and that main class can then call the main(String[]) method on your real main class (that way, the Java launcher doesn't require the javafx libraries to be available as named modules). See https://stackoverflow.com/questions/52569724/javafx-11-create-a-jar-file-with-gradle/52571719#52571719 or https://stackoverflow.com/questions/52569724/javafx-11-create-a-jar-file-with-gradle/52615808#52615808
I can try later to reproduce, but you are using Java 10, which includes JavaFX, and then adding JavaFX 11 dependencies. That looks like a bad idea.
OpenJDK does not include OpenJFX as far as I know?
There are some easy workarounds though. For example, you can have a main class that is not extending javafx.application.Application, and that main class can then call the main(String[]) method on your real main class (that way, the Java launcher doesn't require the javafx libraries to be available as named modules).
Thanks, now it works. Next step I need to figure out how to bundle all the native libraries (windows, mac, linux) instead of only one.
OpenJDK does not include OpenJFX as far as I know?
Only from 11. You are using Java 10, which includes JavaFX 10.
Java 10
Oracle JDK 10 include JavaFX, OpenJDK 10 does not. I'm using OpenJDK 10.
Sorry, I quickly saw Java version: 10.0.2, vendor: Oracle Corporation and thought you were using Oracle JDK 10.
Working example: src/Main.java
public class Main {
public static void main(String[] args) {
HelloFX.main(args);
}
}
src/HelloFX.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
//import javafx.graphics;
public class HelloFX extends Application {
@Override
public void start(Stage stage) {
String javaVersion = System.getProperty("java.version");
String javafxVersion = System.getProperty("javafx.version");
Label l = new Label("Hello, JavaFX " + javafxVersion + ", running on Java " + javaVersion + ".");
Scene scene = new Scene(l, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
pom.xml
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>HelloFX</groupId>
<artifactId>HelloFX</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>10</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</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>
</project>
We also ran into Error: JavaFX runtime components are missing, and are required to run this application. The only thing we had to change in our pom.xml was setting a regular Java class as entry point which then called a JavaFX Application in its main like @klausenbusk showed.
Can't thank you enough @klausenbusk
Ran into this just now, when running the Non Modular Gradle sample from Intellij on Java 11. The message "Error: JavaFX runtime components are missing, and are required to run this application" sounds like something fundamental is missing from your system. But you can just create another class (which doesn't subclass Application) with a main method which simply calls your Application-class main method - and it then works from Intellij You will have people giving up on Java FX because of this issue - I nearly did myself!
Isn't it mentioned in https://openjfx.io/openjfx-docs/?
On Mon, Jul 27, 2020 at 2:27 PM davidfrancisandroidemul < [email protected]> wrote:
Ran into this just now, when running the Non Modular Gradle sample from Intellij on Java 11. The message "Error: JavaFX runtime components are missing, and are required to run this application" sounds like something fundamental is missing from your system. But you can just create another class (which doesn't subclass Application) with a main method which simply calls your Application-class main method - and it then works from Intellij You will have people giving up on Java FX because of this issue - I nearly did myself!
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/javafxports/openjdk-jfx/issues/236#issuecomment-664340032, or unsubscribe https://github.com/notifications/unsubscribe-auth/AI5QOM55UYBVWWYNRXV6O4LR5VQAHANCNFSM4FYWJUHQ .
@davidfrancisandroidemul Also note that this repo is defunct. The current one is https://github.com/openjdk/jfx.
The error is indeed mentioned, but in a different section than the one I was following And the solution documented in there didn't work Before I found the "create a new class" solution, I did clone the samples from the page (linked above by nlisker) and tried them - got the same error 8[
OK will try the new repo, maybe the new examples work?
I've never had a problem with the instructions, so from my point of view the examples worked and still work.
If you have a problem specifically with the examples, file an issue with https://github.com/openjfx/openjfx.github.io, which is the repository for the openjfx.io website. The https://github.com/openjdk/jfx repository is for issues with JavaFX itself.