Home > Mobile >  JavaFX and Gradle: What is the correct way to load a default view?
JavaFX and Gradle: What is the correct way to load a default view?

Time:04-05

I keep getting "Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0."

I've looked and tried a dozen fixes and tutorials all with the same error. I've moved the view to the every folder and renamed it incase underscores aren't allowed. I've tried every permutation of "/path/file.fxml" I can think of

I have a feeling my code is depreciated but all I can do is get intellij to highlight .load()

Here is my code:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class ScoreSheet extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
    FXMLLoader fxmlLoader = new 
FXMLLoader(ScoreSheet.class.getResource("views/main_menu.fxml"));
    primaryStage.setTitle("Score Sheet");
    Group root = new Group();
    Scene scene = new Scene(fxmlLoader.load(), 405, 720);
    primaryStage.setScene(scene);
    primaryStage.show();

    }
}

Here is my stacktrace:

Starting Gradle Daemon...
Connected to the target VM, address: '127.0.0.1:51285', transport: 'socket'
Gradle Daemon started in 616 ms

> Configure project :
Found module name 'ScoreSheetTest.main'
Disconnected from the target VM, address: '127.0.0.1:51285', transport: 'socket'

> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE
> Task :jar UP-TO-DATE
Connected to the target VM, address: 'localhost:51290', transport: 'socket'
Disconnected from the target VM, address: 'localhost:51290', transport: 'socket'
Connected to the target VM, address: '127.0.0.1:51285', transport: 'socket'

> Task :ScoreSheet.main() FAILED

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.2/userguide/command_line_interface.html#sec:command_line_warnings
3 actionable tasks: 1 executed, 2 up-to-date
Exception in Application start method
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1071)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.IllegalStateException: Location is not set.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2541)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2516)
    at ScoreSheetTest.main/com.company.scoresheet.ScoreSheet.start(ScoreSheet.java:16)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':ScoreSheet.main()'.
> Process 'command '/Users/username/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1


BUILD FAILED in 4s
Disconnected from the target VM, address: '127.0.0.1:51285', transport: 'socket'
2:05:57 PM: Execution finished ':ScoreSheet.main()'.

Edit: File structure image File Structure Image

Edit 2: Here is my build.gradle:

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

group 'com.iharptech'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    implementation 'org.openjfx:javafx-controls:18'
}

test {
    useJUnitPlatform()
}

sourceSets {
    main {
        resources {
            srcDirs = ["src/main/java"]
            includes = ["**/*.fxml"]
        }
    }
}

CodePudding user response:

Gradle Deprecation Warnings

These warnings are almost certainly not related to your IllegalStateException.

If you want to know which deprecated features were used, then you can do what the warning message says and use --warning-mode all. If the features were used by your own build script, then you can look up the replacements and fix the problem yourself. However, if the features were used by a plugin then really your only options are: (1) Update to use the latest version of the plugin; (2) If already using the latest version, submit a bug report with the plugin authors (if one doesn't already exist); (3) Maybe, if possible, use a different plugin.


Using Gradle with an IDE

When you use a build tool such as Gradle (or e.g., Maven), then you should let the build tool handle all dependencies and other configurations (as much as is possible). In other words, you should be declaring the JavaFX dependencies in your build script, not in IntelliJ.

You should also have the IDE delegate build and run tasks to Gradle. That way Gradle is responsible for everything build related, and the IDE is only responsible for making it easier to write code.

IntelliJ works really well with Gradle. Any dependencies you add to Gradle will be known by IntelliJ. And any tasks supplied by Gradle will also be known by IntelliJ.

Declare JavaFX Dependencies in Gradle

You're using the OpenJFX javafx-gradle-plugin. That project's README has documentation for how to declare which JavaFX modules you need for your project. Note the latest version of this plugin is 0.0.12. You should update your build script to use that version.

Local JavaFX SDK

If you're using a downloaded JavaFX SDK, as your comments seem to imply, then you can use:

javafx {
    sdk = '/path/to/sdk' // replace with your own path
    modules = ['javafx.controls', 'javafx.fxml'] // modify list as needed
}

For the sdk path, you may want to setup a variable that is then passed by the person who invokes Gradle. That way people on other computers can still build your project without modifying the build script. Though if this is a personal project on a single computer then a static, absolute path should be fine for now.

I don't know when this feature was added to the plugin, so you may need to update to the latest version.

Maven Central JavaFX JARs

You could instead have Gradle download the needed JavaFX JAR files from Maven Central.

javafx {
    modules = ['javafx.controls', 'javafx.fxml'] // modify list as needed
    version = '18' // change version as needed
}

repositories {
    mavenCentral()
}

Executing Gradle Tasks

You should make run configurations to execute Gradle tasks, rather than letting the IDE use its own build and execution system.

To execute any Gradle task via IntelliJ, you can open up the Gradle tab (typically on the right side of IntelliJ, if I'm not mistaken), select a task, and execute it.

Or you could manually create a "run configuration". Make sure to choose "Gradle" when selecting the type of configuration. Tell it which project the task is for and which task to execute.

The Application Plugin

Typically, with JVM projects, when you want to be able to execute your project you should apply the application plugin.

plugins {
    // other plugins...
    'application'
}

You already do this. But you also need to configure the main class and, if present, the main module.

application {
    mainModule = '<module-name>'
    mainClass = '<fully-qualified-class-name>'
}

The application plugin adds the run task. To execute your project, have IntelliJ execute the run task.


Resources

For general information about resources, how to load them, what paths to use, and some troubleshooting techniques, I recommend this Q&A:

How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?

But specifically regarding your setup, you should remove this part from your Gradle build script:

sourceSets {
    main {
        resources {
            srcDirs = ["src/main/java"]
            includes = ["**/*.fxml"]
        }
    }
}

It's not needed. Keeping it means src/main/resources is no longer considered a resource root, which you probably do not want.

With that change, and executing the project via the run task, using "/views/main_menu.fxml" should work for you as the resource path.

  • Related