FearX
FearX

Reputation: 317

NullPointerException when loading an FXML

I am getting a NullPointerException regarding the location of my FXML. However, this only started to happen after I upgraded my JavaFX version (I need 13 to meet project requirements).

My main class:

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws IOException {

    String path = "/fxml/loginScene.fxml";

    Parent root = FXMLLoader.load(getClass().getResource(path));
    primaryStage.initStyle(StageStyle.UNDECORATED);

    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/imgs/icon.png")));
    primaryStage.show();
}

public static void main(String[] args) {
    launch(args);
}
}

module-info:

module main {
requires javafx.controls;
requires javafx.fxml;
requires jfoenix;
requires vlcj;

opens me.fullcam.mosaicov2 to javafx.fxml;
exports me.fullcam.mosaicov2;
}

My directories:

enter image description here

The exception:

    Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.NullPointerException: Location is required.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3230)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
    at main/me.fullcam.mosaicov2.Main.start(Main.java:20)

My build.gradle:

    plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'org.beryx.jlink' version '2.12.0'
}

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'uk.co.caprica', name: 'vlcj', version: '4.2.0'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.0.1'
    compile group: 'com.google.http-client', name: 'google-http-client', version: '1.23.0'
    compile group: 'com.jfoenix', name: 'jfoenix', version: '8.0.9'
    compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.28'
}

javafx {
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml' ]
}

mainClassName = "$moduleName/me.fullcam.mosaicov2.Main"

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'mosaico-desktop'
    }
}

I think that everything is in order, but resources aren't being added to the classpath. I have not found anything like that. I'm using IntelliJ.

I've tryied ./gradlew clean --info run, but that's my stacktrace:

> Task :run FAILED
Task ':run' is not up-to-date because:
  Task has not declared any outputs despite executing actions.
Starting process 'command '/usr/lib/jvm/java-12-oracle/bin/java''. Working directory: /home/leonardo/Modelos/IdeaProjects/FullCam/Desktop/mosaico-desktop-v2 Command: /usr/lib/jvm/java-12-oracle/bin/java --add-modules javafx.base,javafx.controls,javafx.fxml,javafx.graphics,javafx.media --module-path /home/leonardo/Modelos/IdeaProjects/FullCam/Desktop/mosaico-desktop-v2/build/classes/java/main:/home/leonardo/Modelos/IdeaProjects/FullCam/Desktop/mosaico-desktop-v2/build/resources/main:/root/.gradle/caches/modules-2/files-2.1/uk.co.caprica/vlcj/4.2.0/727b20426956174d64c6817367f45080ad95a4d0/vlcj-4.2.0.jar:/root/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.0.1/1d160beb3f8924d5b98d03d94a149021146f71cc/jackson-databind-2.0.1.jar:/root/.gradle/caches/modules-2/files-2.1/com.google.http-client/google-http-client/1.23.0/8e86c84ff3c98eca6423e97780325b299133d858/google-http-client-1.23.0.jar:/root/.gradle/caches/modules-2/files-2.1/com.jfoenix/jfoenix/8.0.9/71da4db8303be22f6366df8933dd93519398c8f8/jfoenix-8.0.9.jar:/root/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-simple/1.7.28/cf5f2cf3c31e0e41b68d932d756398a1238d4456/slf4j-simple-1.7.28.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-fxml/13/2c1016c361ce5797927e9e14847fbca9bebf3bd5/javafx-fxml-13-linux.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/13/bcedf8eb6e11c2a7908b3126004d41274f6334f3/javafx-controls-13-linux.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-controls/13/6cd7169d2a729846c35fba9dc65af23a10ca253b/javafx-controls-13.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-media/13/d3626ef7290012a1e55a32532977ed78edc02548/javafx-media-13-linux.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/13/d853d12684f60037dfeea1a47e61396e0febfdfd/javafx-graphics-13-linux.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-graphics/13/a9407212df2b75d557a509ec14a9e8e282494b4e/javafx-graphics-13.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/13/828b1e1a35104bb0f26a347c2716d553ca4cf4d2/javafx-base-13-linux.jar:/root/.gradle/caches/modules-2/files-2.1/org.openjfx/javafx-base/13/43c52e1d11b38514e9d2421ad98ca6a35de12b0/javafx-base-13.jar:/root/.gradle/caches/modules-2/files-2.1/uk.co.caprica/vlcj-natives/4.1.0/d45eb15ac25a1c085a365166d430435bd990409d/vlcj-natives-4.1.0.jar:/root/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.0.1/36e5996abe8655a6471b82af5ac1cd6786aecf85/jackson-annotations-2.0.1.jar:/root/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.0.1/481d14ec21e034ed45217c4854dbbf15940ce108/jackson-core-2.0.1.jar:/root/.gradle/caches/modules-2/files-2.1/com.google.code.findbugs/jsr305/1.3.9/40719ea6961c0cb6afaeb6a921eaa1f6afd4cfdf/jsr305-1.3.9.jar:/root/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpclient/4.0.1/1d7d28fa738bdbfe4fbd895d9486308999bdf440/httpclient-4.0.1.jar:/root/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/1.7.28/2cd9b264f76e3d087ee21bfc99305928e1bdb443/slf4j-api-1.7.28.jar:/root/.gradle/caches/modules-2/files-2.1/net.java.dev.jna/jna-platform/5.2.0/5520c6f3382801576547dd20854225ae2899b649/jna-platform-5.2.0.jar:/root/.gradle/caches/modules-2/files-2.1/net.java.dev.jna/jna/5.2.0/ed8b772eb077a9cb50e44e90899c66a9a6c00e67/jna-5.2.0.jar:/root/.gradle/caches/modules-2/files-2.1/org.apache.httpcomponents/httpcore/4.0.1/e813b8722c387b22e1adccf7914729db09bcb4a9/httpcore-4.0.1.jar:/root/.gradle/caches/modules-2/files-2.1/commons-logging/commons-logging/1.1.1/5043bfebc3db072ed80fbd362e7caf00e885d8ae/commons-logging-1.1.1.jar:/root/.gradle/caches/modules-2/files-2.1/commons-codec/commons-codec/1.3/fd32786786e2adb664d5ecc965da47629dca14ba/commons-codec-1.3.jar --patch-module main=/home/leonardo/Modelos/IdeaProjects/FullCam/Desktop/mosaico-desktop-v2/build/resources/main --module main/me.fullcam.mosaicov2.Main -Dfile.encoding=UTF-8 -Duser.country=BR -Duser.language=pt -Duser.variant main/me.fullcam.mosaicov2.Main
Successfully started process 'command '/usr/lib/jvm/java-12-oracle/bin/java''
/home/leonardo/Modelos/IdeaProjects/FullCam/Desktop/mosaico-desktop-v2/.
Exception in Application start method
java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:835)
Caused by: java.lang.NullPointerException: Location is required.
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3230)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
        at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
        at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
        at main/me.fullcam.mosaicov2.Main.start(Main.java:22)
        at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:389)
        at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
        at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
        at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
        ... 1 more
Exception running application me.fullcam.mosaicov2.Main
:run (Thread[Task worker for ':',5,main]) completed. Took 0.574 secs.

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':run'.
> Process 'command '/usr/lib/jvm/java-12-oracle/bin/java'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
5 actionable tasks: 5 executed

Upvotes: 1

Views: 2100

Answers (2)

José Pereda
José Pereda

Reputation: 45456

Based on the posted MVCE project, these are a few modifications that are required to make the project work:

build.gradle

Based on this:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'org.beryx.jlink' version '2.12.0'
}

group 'me.project.desktop'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'uk.co.caprica', name: 'vlcj', version: '4.2.0'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.0.1'
    compile group: 'com.google.http-client', name: 'google-http-client', version: '1.23.0'
    compile group: 'com.jfoenix', name: 'jfoenix', version: '8.0.9'
    compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.28'
}

javafx {
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.base', 'javafx.graphics', 'javafx.media' ]
}

mainClassName = "me.project.mosaic.Main"

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'mosaico-desktop'
    }
}

The required changes are:

  • Set Java level to 11

  • Update dependencies

JFoenix is set to 8.0.9, that is intended for Java 1.8. If you run with Java 11+, you will get an exception:

Caused by: java.lang.ClassNotFoundException: com.sun.javafx.css.converters.PaintConverter
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)

Since JDK 9, CSS converters are public API, so you need JFoenix for 9, like 9.0.9.

See for reference this post.

  • Use JDK 11, not 12 or 13

JFoenix's JFXTextField control has an standing issue with the use of reflection to access private API.

java.lang.IllegalAccessException: class com.jfoenix.skins.JFXTextFieldSkin cannot access a member of class javafx.scene.control.skin.TextFieldSkin (in module javafx.controls) with modifiers "private"
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:376)
...
java.lang.IllegalAccessException: class com.jfoenix.skins.JFXTextFieldSkin cannot access a member of class javafx.scene.control.skin.TextFieldSkin (in module javafx.controls) with modifiers "private"
        at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:376)
        at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:639)
...  

and that causes a null pointer exception:

Caused by: java.lang.NullPointerException
        at com.jfoenix.skins.JFXTextFieldSkin.updateTextPos(JFXTextFieldSkin.java:109)

Running with Java 11, it works fine.

For reference, see this post.

  • Add exports

JFoenix uses private API, so it requires a bunch of exports, that have to be added to the VM arguments, like:

run {

    jvmArgs = [

        "--add-exports=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED",

        "--add-exports=javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED",

        "--add-exports=javafx.base/com.sun.javafx.binding=ALL-UNNAMED",
        "--add-exports=javafx.graphics/com.sun.javafx.stage=ALL-UNNAMED",
        "--add-exports=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED"
    ]

}

For reference, see this.

This will be the resulting build.gradle file:

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'org.beryx.jlink' version '2.12.0'
}

group 'me.project.desktop'
version '1.0-SNAPSHOT'

sourceCompatibility = 11

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'uk.co.caprica', name: 'vlcj', version: '4.2.0'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.0.1'
    compile group: 'com.google.http-client', name: 'google-http-client', version: '1.23.0'
    compile group: 'com.jfoenix', name: 'jfoenix', version: '9.0.9'
    compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.28'
}

javafx {
    version = "13"
    modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.base', 'javafx.graphics', 'javafx.media' ]
}

run {
    jvmArgs = ["--add-exports=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED",
        "--add-exports=javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED",
        "--add-exports=javafx.base/com.sun.javafx.binding=ALL-UNNAMED",
        "--add-exports=javafx.graphics/com.sun.javafx.stage=ALL-UNNAMED",
        "--add-exports=javafx.controls/com.sun.javafx.scene.control.behavior=ALL-UNNAMED"
    ]
}

mainClassName = "me.project.mosaic.Main"

jlink {
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'mosaico-desktop'
    }
}

Running (with JDK 11):

./gradlew clean run

will work.

Modular project

In order to run jlink, you need to create a modular descriptor, like:

module mosaic.viewer {
    requires javafx.controls;
    requires javafx.fxml;
    requires com.jfoenix;
    requires vlcj;
    requires jackson.annotations;
    requires jackson.databind;
    requires jackson.core;
    requires google.http.client;
    requires org.slf4j;
    requires jsr305;

    opens me.project.mosaic.login to javafx.fxml;
    exports me.project.mosaic;
}
  • Open package

Since FXML uses reflection, you have to open to the javafx.fxml module the package(s) with the controller(s). In this case: opens me.project.mosaic.login to javafx.fxml;.

  • Add exports

Since you have a named module now, the --add-exports are now set to com.jfoenix instead of ALL-UNNAMED.

Running (with JDK 11):

./gradlew clean jlink

will create a custom image, and you will be able to run the generated image from the launcher script:

build/image/bin/mosaic-desktop

IDE

If you run the project from your IDE (IntelliJ) and not from a terminal, make sure you use the Gradle window for IntelliJ, that will show you the project and available tasks.

It is important to set in Project Structure -> Project the project SDK and language level to 11.

Also, the Gradle window has a settings button, click on it, and make sure that the Gradle JVM is also set to JDK 11.

You can run from this window:

  • Tasks -> application -> run

  • Tasks -> build -> jlink

Finally, you can also create Run configurations, but based on Gradle, with the above tasks.

Upvotes: 2

ᴇʟᴇvᴀтᴇ
ᴇʟᴇvᴀтᴇ

Reputation: 12751

Yes, the Location is required exception means that the resource passed into the FXMLLoader.load(...) method was null—i.e. not on your classpath.

It could be that you have supplied the wrong path or that you're using the wrong classloader or that you have misconfigured your classpath when you run the application. Perhaps that file is in your source folder but not being copied into the classes folder?

It's hard to debug from here. You need to work out where that .fxml file is located and make sure that it is on the classpath.

Alternatively, you could load it from a file. E.g.

URL url = new File("C:/fxml/loginScene.fxml").toURI().toURL();
Parent root = FXMLLoader.load(url);

Upvotes: -1

Related Questions