I am building a TornadoFx (JavaFX for Kotlin) application. I never had a problem running the application with gradle, but building it into a jar and executing said jar has been a struggle.
Through much trial and error, I have found that I cannot simply run java -jar App.jar, but instead I have to add the following arguments to add in the proper dependencies for JavaFX --module-path /usr/share/openjfx/lib/ --add-modules javafx.controls. But I would like to implement this through gradle, so that these modules are bundled with the jar so that it can be distributed and used by others much nicer.
I have tried to add the JavaFX dependencies 2 different ways, but neither worked:
- Implementing the OpenJFX maven artifacts as dependencies
- Adding
includeBuild("/usr/share/openjfx/lib")tosettings.gradle.kts
Thank you to anyone who is able to help out.
Below are all the details of the application and build process:
- JDK 1.8
- Kotlin 1.4.32
- Gradle Kotlin DSL
- Source Code: GitHub
Here is my build.gradle.kts
import no.tornado.fxlauncher.gradle.FXLauncherExtension
buildscript {
repositories {
mavenCentral()
}
}
plugins {
application
kotlin("jvm") version "1.4.32"
id("no.tornado.fxlauncher") version "1.0.20"
}
group = "com.jtschwartz"
version = "1.0.0"
val kotlinVersion: String by rootProject
val tornadoFxVersion: String by rootProject
repositories {
mavenCentral()
}
application {
mainClassName = "com.jtschwartz.scratchpad.ScratchpadKt"
}
configure<FXLauncherExtension> {
applicationVendor = "Jacob Schwartz ([email protected])"
applicationUrl = "https://storage.googleapis.com/jts-scratchpad-bucket"
applicationMainClass = application.mainClassName
applicationVersion = "1.0.2"
applicationTitle = "Scratchpad"
applicationName = "Scratchpad"
}
dependencies {
platform("org.jetbrains.kotlin:kotlin-bom")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion")
implementation("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
implementation("no.tornado:tornadofx:$tornadoFxVersion")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion")
}
tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
}
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = application.mainClassName
}
from(configurations.compileClasspath.get().map {if (it.isDirectory) it else zipTree(it)})
}
tasks.register<Exec>("deployToGCP") {
dependsOn("embedApplicationManifest")
commandLine("gsutil", "cp", "-r", "./build/libs", "gs://jts-scratchpad-bucket")
}
And this is the error I receive when java -jar App.jar is run without the necessary module arguments:
Exception in thread "main" java.lang.NoClassDefFoundError: javafx/application/Application
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
at com.jtschwartz.scratchpad.ScratchpadKt.main(Scratchpad.kt:126)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application
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:522)
... 19 more