11

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)
crosf32
  • 166
  • 1
  • 4
  • 11
  • Did you have a look here: https://openjfx.io/openjfx-docs/#maven – mipa Jul 13 '19 at 14:13
  • Yes i did, but the repo is missing. (javafx-maven-plugin) so i can't use it. – crosf32 Jul 13 '19 at 17:50
  • I found another one in com.zenjava but when i run jfx:run it throws ```Could not find artifact javafx-packager:javafx-packager:jar:1.8.0_20 at specified path C:\Program Files\Java\jdk-11.0.1/../lib/ant-javafx.jar"``` – crosf32 Jul 13 '19 at 17:56
  • What do you mean with the "repo is missing"? You can use the `javafx-maven-plugin` to run JavaFX projects and also to use `jlink`. See the referred documentation and also the plugin's readme: https://github.com/openjfx/javafx-maven-plugin#usage. – José Pereda Jul 13 '19 at 18:24
  • Ok sorry, i got the javafx-maven-plugin. i can run javafx:compile and javafx:run well but javafx:jlink gives me an error : ```Failed to execute goal org.openjfx:javafx-maven-plugin:0.0.2:jlink (default-cli) on project ay-simforest: Error: jlink requires a module descriptor``` – crosf32 Jul 13 '19 at 18:54
  • That means that your project is not modular (yet). You'll need to add `module-info.java`, with the required modules. – José Pereda Jul 13 '19 at 19:34
  • Actually i did. ```module simforest { requires java.base; requires java.desktop; requires java.sql; requires javafx.controls; opens simforest; }``` but it still gives me this error. I put the module-info at the root of the project which seems to be normal.. – crosf32 Jul 13 '19 at 19:57
  • I still have the issue.. (Failed to execute goal org.openjfx:javafx-maven-plugin:0.0.2:jlink (default-cli) on project ay-simforest: Error: jlink requires a module descriptor) there is a module-info.java though – crosf32 Jul 14 '19 at 11:50
  • Can you edit your question and post enough details so we can reproduce your issue? Otherwise it is hard to say. At least your module-info and the project structure? – José Pereda Jul 15 '19 at 10:41
  • First, the openjfx maven example referred to by the first comment is useless. It's a hello world example, and certainly not going to help anyone figure out how to make a real pom file for a real JavaFx application. – shawn1874 Sep 29 '19 at 05:29

2 Answers2

28

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!

chowmein
  • 298
  • 3
  • 5
  • 2
    you are a MASTERMIND, I was struggling with this for DAYS :) – darthgamer64 Apr 27 '21 at 15:35
  • 1
    But wait I get that pipeline error when trying to run a jar in different OS. For instance if I compile in windows, that jar gives me issues running in Mac OS. Is there any way around that? – darthgamer64 Apr 28 '21 at 03:43
  • @darthgamer64 Sorry I can't be of any help. I haven't built a cross-platform jar file before so that doesn't sound familiar to me--although it should work in theory. Did you ever figure out what the issue is? One guess I have is because the Mac you're trying to run it on doesn't have JRE installed? – chowmein Nov 19 '21 at 08:15
  • And after finishing this brilliant guideline, add the additional configuration mentioned [here](https://stackoverflow.com/a/6743609/9492722) to the shade plugin to avoid __"SecurityException: Invalid signature"__ error. – FdelS Aug 16 '23 at 23:41
1

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

Dharman
  • 30,962
  • 25
  • 85
  • 135
cyrano1960
  • 11
  • 1
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30195634) – eglease Oct 28 '21 at 13:27