0

I'm developing an app using JavaFX, but I've encountered a problem creating a build and converting it into an executable app. Several years ago, I created a small app using this technology, and I remember that Intellij IDEA allowed me to create a native executable for almost any desktop operating system (Windows, Mac, or Linux). However, that strategy didn't work for me in this project. According to what I've been reading online, the JavaFX project was natively separated from the Oracle JDK, so it needs to be run independently.

I'm developing this new project with Oracle OpenJDK 23 and intending to use it only in Windows environments. I've been researching how to create an executable build of this app using Maven plugins (I've already tried some variants) and nothing has worked. I managed to get the resulting .jar file to be of shade type and contain all the libraries used by the project. I've attached my pom.xml file.

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>cu.nerzur</groupId>
 <artifactId>WallpaperEngine</artifactId>
 <version>0.2.2</version>
 <name>WallpaperEngine</name>
 <description>WallpaperEngine</description>
 <properties>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <junit.version>5.10.2</junit.version>
 <java.version>23</java.version>
 </properties>
 <dependencies>
 <!-- reduce boiler plate -->
 <dependency>
 <groupId>com.sangupta</groupId>
 <artifactId>jerry-core</artifactId>
 <version>3.0.1</version>
 </dependency>
 <!-- for making HTTP calls -->
 <dependency>
 <groupId>com.sangupta</groupId>
 <artifactId>jerry-http</artifactId>
 <version>2.0.0</version>
 </dependency>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.18.38</version>
 <optional>true</optional>
 <scope>provided</scope>
 </dependency>
 <dependency>
 <groupId>net.java.dev.jna</groupId>
 <artifactId>jna</artifactId>
 <version>5.13.0</version>
 </dependency>
 <dependency>
 <groupId>net.java.dev.jna</groupId>
 <artifactId>jna-platform</artifactId>
 <version>5.13.0</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
 <dependency>
 <groupId>org.openjfx</groupId>
 <artifactId>javafx-controls</artifactId>
 <version>26-ea+3</version>
 </dependency>
 <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
 <dependency>
 <groupId>org.openjfx</groupId>
 <artifactId>javafx-fxml</artifactId>
 <version>26-ea+3</version>
 </dependency>
 <dependency>
 <groupId>org.openjfx</groupId>
 <artifactId>javafx-swing</artifactId>
 <version>26-ea+3</version>
 </dependency>
 <dependency>
 <groupId>org.junit.jupiter</groupId>
 <artifactId>junit-jupiter-api</artifactId>
 <version>${junit.version}</version>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.junit.jupiter</groupId>
 <artifactId>junit-jupiter-engine</artifactId>
 <version>${junit.version}</version>
 <scope>test</scope>
 </dependency>
 <!-- for JSON parsing -->
 <dependency>
 <groupId>com.google.code.gson</groupId>
 <artifactId>gson</artifactId>
 <version>2.13.1</version>
 </dependency>
 </dependencies>
 <build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-compiler-plugin</artifactId>
 <version>3.14.0</version>
 <configuration>
 <release>23</release>
 <annotationProcessorPaths>
 <path>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>1.18.38</version>
 </path>
 </annotationProcessorPaths>
 <compilerArgs>
 <arg>-Xlint:all</arg>
 </compilerArgs>
 </configuration>
 </plugin>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-shade-plugin</artifactId>
 <version>3.6.0</version>
 <executions>
 <execution>
 <phase>package</phase>
 <goals>
 <goal>shade</goal>
 </goals>
 <configuration>
 <transformers>
 <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
 <mainClass>com.nerzur.wallpaperengine.Init</mainClass>
 </transformer>
 </transformers>
 <filters>
 <filter>
 <artifact>*:*</artifact>
 <excludes>
 <exclude>META-INF/*.SF</exclude>
 <exclude>META-INF/*.DSA</exclude>
 <exclude>META-INF/*.RSA</exclude>
 </excludes>
 </filter>
 </filters>
 </configuration>
 </execution>
 </executions>
 </plugin>
 <plugin>
 <groupId>org.openjfx</groupId>
 <artifactId>javafx-maven-plugin</artifactId>
 <version>0.0.8</version>
 <executions>
 <execution>
 <id>default-cli</id>
 <configuration>
 <mainClass>com.nerzur.wallpaperengine.Init</mainClass>
 <launcher>app</launcher>
 <jlinkZipName>app</jlinkZipName>
 <jlinkImageName>app</jlinkImageName>
 <noManPages>true</noManPages>
 <stripDebug>true</stripDebug>
 <noHeaderFiles>true</noHeaderFiles>
 </configuration>
 </execution>
 </executions>
 </plugin>
 </plugins>
 </build>
</project>

But I still can't get the Java FX runtimes to be included, and I get an error message when running the jar with the command java -jar app.jar.

Error when execute the jar using java -jar command

Some solutions mention using a module-info.java file to create a Java module that includes JavaFX dependencies. However, when creating this file, errors start to appear because I'm using dependencies that aren't backed by modules, or so it seems. I'm not currently using this file, but when I had it integrated into the project, it looked something like this.

module com.nerzur.WallpaperEngine {
 requires javafx.controls;
 requires javafx.fxml;
 requires javafx.graphics;
 requires java.desktop;
 requires transitive static lombok;
 requires transitive slf4j.api;
 requires transitive jerry.http;
 requires transitive jerry.core;
 requires transitive java.net.http;
 requires transitive com.google.gson;
 requires transitive com.sun.jna;
 requires transitive com.sun.jna.platform;
 
 opens com.nerzur.wallpaperengine to javafx.fxml;
 opens com.nerzur.wallpaperengine.controller to javafx.fxml;
 
 exports com.nerzur.wallpaperengine;
 exports com.nerzur.wallpaperengine.controller;
 exports com.nerzur.wallpaperengine.service;
 exports com.nerzur.wallpaperengine.scheduledTask;
 exports com.nerzur.wallpaperengine.util;
}

The only solution I've found to make this project compilable is to use Launch4j (an external app) using the current pom.xml and deleting the module-info.java file. Then, pass a fixed path for the JRE and another path with the JVM execution options as parameters with the following command: --module-path "C:\WallpaperEngine\libs\javafx-sdk-24.0.2\lib" --add-modules javafx.controls,javafx.fxml,javafx.swing" which indicates the absolute path of the JavaFX SDK. This forces me to copy the app to an absolute path on the PC and include both SDKs in the compiled APK (which doesn't seem optimal to me).

Is there any other way to create an executable for this type of application that doesn't involve such drastic methods? Thanks in advance.

asked 4 hours ago
4
  • 1
    "I get an error message" you have to add the complete error to the question so people can help you to solve it. Commented 3 hours ago
  • For Launch4j, suppose your app directory is C:\WallpaperEngine. Then the parameter should be adjusted to use a relative directory: .\libs\javafx-sdk-24.0.2\lib --> --module-path ".\libs\javafx-sdk-24.0.2\lib" Commented 3 hours ago
  • @life888888 thanks, applying the idea you mentioned about using relative paths I was able to run the app in any directory using launch4j, the --module-path command changed to this: --module-path "%EXEDIR%\libs\javafx-sdk-24.0.2\lib" --add-modules javafx.controls,javafx.fxml,javafx.swing Commented 1 hour ago
  • The JDK comes with a tool that does this. I don't usually build with Maven, but I assume this plugin is the one you would want to use. Commented 52 mins ago

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.