Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build executable JAR with JavaFX11 from maven

I've made a Java app which uses Maven, JavaFX and some other dependencies. Before, it was easy to build an executable jar but since Java11 is modular and does not include JavaFX i just can't build a working one.

I've already tried a lot of things but i don't know what i'm supposed to do now.

My pom.xml

 <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <verbose>true</verbose>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <outputDirectory>out/</outputDirectory>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>fr.crosf32.fxtest.Entry</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

I've tried to build artifact with all dependencies inside but i obtain an error when i run (java -jar ):

Exception in thread "Thread-0" java.lang.NoClassDefFoundError: javafx/application/Application
        at java.base/java.lang.ClassLoader.defineClass1(Native Method)
        at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
        at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
        at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
        at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        at fr.crosf32.fxtest.SlimForest.lambda$new$0(SlimForest.java:26)
        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        ... 11 more

EDIT

I've tried to build a jar which contains JavaFX using Jlink but when i try to run the app i obtain :

Graphics Device initialization failed for :  d3d, 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:280)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.init(QuantumToolkit.java:222)
        at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:260)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:834)
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:94)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
        ... 1 more
Exception in thread "Thread-0" java.lang.RuntimeException: No toolkit found
        at javafx.graphics/com.sun.javafx.tk.Toolkit.getToolkit(Toolkit.java:272)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:267)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:834)
like image 277
crosf32 Avatar asked Jul 13 '19 12:07

crosf32


People also ask

How will you create JAR file of the project using Maven?

To create a JAR file from a Maven project in IntelliJ IDEA, go to the Maven Tool Window (View → Tool Windows → Maven), expand your project in the tree, expand Lifecycle, and then double-click on package. Maven will compile your package, and the compiled JAR file will be written to the target/ directory.

How do I package a jar with dependencies?

Use the maven-shade-plugin to package all dependencies into one über-JAR file. It can also be used to build an executable JAR file by specifying the main class.


2 Answers

I struggled through the process of creating an executable jar as well, but this workaround is what worked for me, and I hope it works for you as well:

First of all, instead of using the jar plugin, I used the shade plugin in pom.xml, which creates a "fat jar" or "uber jar" that contains your classes and all of the dependencies within the jar. This way, your jar will be included with all the necessary javafx packages and classes. That is, if you include these in the <dependencies> section:

<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-graphics</artifactId>
    <version>11</version>
</dependency>
<dependency>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-controls</artifactId>
    <version>11</version>
</dependency>

... or whatever else of the javafx libraries you need in order for your application to run.

Simply doing this does not work, however. I'm assuming that your main class Entry extends Application?

I'm guessing the jar needs to know the actual Main class that does not extend Application, so I just created another Main class called SuperMain (it was only a temporary name) that calls my original main class, which is Main:

// package <your.package.name.here>

public class SuperMain {
    public static void main(String[] args) {
        Main.main(args);
    }
}

whereas in your case it's Entry.

So in my pom.xml, I have a plugin called shade that looks like this:

<plugin>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.1</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <mainClass>my.package.name.SuperMain</mainClass>
                    </transformer>
                </transformers>
            </configuration>
        </execution>
    </executions>
</plugin>

and there should be a jar that's "shaded" after you execute mvn package.

Thanks to the answer to this post: JavaFX 11 : Create a jar file with Gradle

Hope this helps!

like image 162
chowmein Avatar answered Sep 28 '22 10:09

chowmein


even if it´s a long time ago but maybe there are some other guys searching for this answer: you have to include os classifier in your pom.xml here is an excellent tutorial for this:

https://youtu.be/w_PsCNqqcE4?list=PL4h6ypqTi3RR_bhBk6PtLfD83YkaJXXxw

like image 29
cyrano1960 Avatar answered Sep 28 '22 09:09

cyrano1960