I am using JavaExec tasks to run different classes, but whenever I try to run one of the tasks using gradle <task>
, I get an error saying Error: JavaFX runtime components are missing, and are required to run this application
.
If I just set mainClassName='exercise1.Cards'
or whatever other className, running gradle run
works completely fine. I'm guessing that the JavaFX classes are not found when running classes with JavaExec and I'm wondering how I can include them.
build.gradle:
plugins {
id 'java'
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.7'
}
version '1.0-SNAPSHOT'
sourceCompatibility = 11
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
javafx {
modules = [ 'javafx.controls' ]
}
task runExercise1(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'exercise1.Cards'
}
task runExercise2(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'exercise2.InvestmentCalculator'
}
task runExercise3(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'exercise3.PointCircle'
}
task runExercise4(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'exercise4.OccurrenceHistogram'
}
The org.openjfx.javafxplugin
plugin manages for you a few things.
When you add to your build file:
javafx {
modules = [ 'javafx.controls' ]
}
the plugin translates that into something like:
run {
doFirst {
jvmArgs = ['--module-path', classpath.asPath,
'--add-modules', 'javafx.controls']
}
}
However, if you create a new JavaExec
task, it seems the plugin doesn't process it.
Given the error you have posted:
Error: JavaFX runtime components are missing
it is clear that a possible fix is to do exactly what the plugin does and add the expected jvm args when using modular dependencies.
So this should work:
task runExercise1(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
jvmArgs = ['--module-path', classpath.asPath,
'--add-modules', 'javafx.controls' ]
main = 'exercise1.Cards'
}
Alternatively you could create a launcher class that doesn't extend from Application
, as that will bypass the modular check (as explained here).
public class Launcher {
public static void main(String[] args) {
// optionally process args to select class to run
Cards.main(args);
}
}
Then you could add your task, and even uses runtime arguments to select the main class to run from the launcher.
task runExercise1(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'exercise1.Launcher'
args 'exercise1' // <-- optionally select class to run
}