0

I have a little maven test project to build a very simple javaFX application. I have set up maven that it creates (install task) a .jar file including all dependencies for this project. Since javaFX is not part of the standard JREs/JDKs is thought that would be a good idea.

I was already able to successfully start the application on my Windows10 PC just by double-clicking on the jar with the dependencies. Building it without the dependencies results in an error, since javaFX is missing in the JRE. So far so good.

However, sitting on my Manjaro Linux PC now, i am unable to start the application.

The code for the project is 100% identical (just cloned the repo). Double clicking the .jar doesn't work, neither does trying to execute it from a terminal with "java -jar APP", leading to the error "Used javaFX components missing". What am I missing here, the dependencies should be bundled to the .jar, furthermore it is working under Windows? Btw I am using JDK 12.0.2 on Linux.

Here is my pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>iffuw</groupId>
    <artifactId>javaFX-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

        <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
             </plugin>
            <!-- build a jar with all dependencies -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        </build>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-base -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-base</artifactId>
            <version>13</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>13</version>
        </dependency>
    </dependencies>


</project>

Furthermore my default java version has the javaFX libs:

ls -l /usr/lib/jvm/java-12-openjdk/lib | grep javafx
-rw-r--r-- 1 root root    744481 17. Aug 18:39 javafx.base.jar
-rw-r--r-- 1 root root   2508117 17. Aug 18:39 javafx.controls.jar
-rw-r--r-- 1 root root    125617 17. Aug 18:39 javafx.fxml.jar
-rw-r--r-- 1 root root   4349165 17. Aug 18:39 javafx.graphics.jar
-rw-r--r-- 1 root root    263870 17. Aug 18:39 javafx.media.jar
-rw-r--r-- 1 root root       113 17. Aug 18:39 javafx.properties
-rw-r--r-- 1 root root     87714 17. Aug 18:39 javafx.swing.jar
-rw-r--r-- 1 root root     36678 17. Aug 18:39 javafx-swt.jar
-rw-r--r-- 1 root root    702059 17. Aug 18:39 javafx.web.jar
-rwxr-xr-x 1 root root     26288 17. Aug 18:39 libjavafx_font_freetype.so
-rwxr-xr-x 1 root root     18024 17. Aug 18:39 libjavafx_font_pango.so
-rwxr-xr-x 1 root root     18024 17. Aug 18:39 libjavafx_font.so
-rwxr-xr-x 1 root root    239280 17. Aug 18:39 libjavafx_iio.so

What am I missing here?

EDIT

Sorry I simply don't get it. The project with the above pom.xml works perfectly on a Windows10 PC! Building it in my Manjaro Linux and using "java -jar APPLICATION" always throws an error like "Necessary JavaFX classes missing". Why does it execute on Windows and not on Linux?

Is there a best practice to build a JavaFX application using maven that definitely runs on all systems where a basic JRE is installed?

EDIT_2

I've just discovered, that under Windows10 I can just start the application by double clicking it. From a cmd "java -jar APPLICATION" yields the same error as under Linux "Error: JavaFX runtime components are missing, and are required to run this application". But omitting the "java -jar" in the cmd, the program starts. Trying to start it under Linux omtting the java -jar by "./APPLICATION.jar" I get an error "Cannot execute binary: Error in file format".

EDIT_3

So i managed to modify the application so, that one can run it (both after building it on linux and windows) via "java -jar APPLICATION.jar". The building of a single jar with all the dependencies worked. A suggestion from one of the commented questions made the deal. I had to "clean" the Main.java so that it does not extend the Application from JavaFX. Simply creating a "NewMain" which extends nothing and just calls Main.main(args) was the solution.

However, this solution is quite a workaround, is this really the only option?

iffuw
  • 89
  • 2
  • 10
  • See those `.so` files? Those are native libraries requires by JavaFX. Even if they’re in your “fat jar,” I doubt the operating system can load libraries while they’re inside an archive. You probably can’t distribute a JavaFX application as a single jar file. (And you shouldn’t anyway, because it throws out manifest information that was present in the other jars, like version numbers and signatures.) – VGR Sep 19 '19 at 22:19
  • @VGR In my experience, as well as according to [this answer by José Pereda](https://stackoverflow.com/questions/52653836/maven-shade-javafx-runtime-components-are-missing/52654791#52654791), fat JARs are possible with JavaFX. The linked answer even provides a cross-platform fat JAR solution (haven't tried it though). I believe some internal JavaFX code, if necessary, extracts the native libraries into an external location (e.g. user home directory); note the JAR files downloaded from Maven Central (f.i. when using Maven or Gradle) have the native code embedded in the JAR file. – Slaw Sep 20 '19 at 00:38
  • Possible duplicate of [Maven Shade JavaFX runtime components are missing](https://stackoverflow.com/questions/52653836/maven-shade-javafx-runtime-components-are-missing) – Slaw Sep 20 '19 at 01:54
  • Thank's for the reactions! Please see my EDIT. – iffuw Sep 20 '19 at 06:18
  • Some JavaFX modules (e.g. `javafx.graphics`) depend on platform-specific native code. This means your application must include the native code for the target platform. If you want to target all three supported platforms (Windows, Mac OS, Linux) then you can either have three platform-specific JAR files or include the native code for each platform in a single JAR. You can also look into `jlink` for creating a custom JRE image or `jpackage` for creating native executables/installers—both result in a self-contained application (embedded JRE). Note a JRE also has platform-specific native code. – Slaw Sep 20 '19 at 09:22
  • If you're wondering why if you _build_ the application on Linux then it can also _run_ on Linux, yet when you _build_ on Windows it cannot _run_ on Linux, that's because Maven is handling some things behind-the-scenes. Take a look [Maven Central](https://repo1.maven.org/maven2/org/openjfx/javafx-graphics/13/) and you'll see there are different artifacts available for each platform (e.g. `javafx-graphics-13-win.jar`, `javafx-graphics-13-linux.jar`). Maven will automatically determine the correct artifact to download based on which platform the build is being executed on. – Slaw Sep 20 '19 at 09:25
  • Thanks for the tips! I got the things with platform dependency. I was just wondering why I generally could not execute the .jar on linux, but I worked around that issue (see my edit3). Unfortunately this Workaround is a bit unsatisfying... – iffuw Sep 20 '19 at 09:58
  • Well, you could always require your end users to have a Java distribution installed that includes JavaFX. Such distributions do still exist (e.g. [Zulu Community™](https://www.azul.com/downloads/zulu-community/)). On the other hand, Java on the desktop appears to be moving away from users installing their own JREs and towards applications being deployed with an embedded JRE; that's what [JEP 343: Packaging Tool](https://openjdk.java.net/jeps/343) (i.e. `jpackage`) is for, which is available in JDK 13+. You'd still need a different artifact for each platform, however. – Slaw Sep 20 '19 at 15:51
  • Thank you very much. Case closed :-) – iffuw Sep 20 '19 at 15:55
  • Used the workaround with the second "main class" from here https://stackoverflow.com/questions/52653836/maven-shade-javafx-runtime-components-are-missing/52654791#52654791 – iffuw Oct 04 '19 at 14:49

0 Answers0