JavaFX and maven: NullPointerException: Location i

2019-01-08 13:54发布

问题:

I have been trying to get Maven set up with JavaFX. Even though I was unexperienced with Maven and JavaFX, I didn't expect it to be so much of a challenge. My Java knowledge is pretty solid (including Swing), and didn't expect to have this much difficulty getting it set up.

I started with a JavaFX project supplied by IntelliJ 13.0 Community Edition. The code in my Main class is relatively small:

package sample;

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

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        //getClass().getResource("../../resources/sample.fxml");
        Parent root = FXMLLoader.load(getClass().getResource("../sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


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

and my pom.xml isn't too big either:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>sample</groupId>
    <artifactId>JavaFXDemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <organization>
        <name>RubberDucky</name>
    </organization>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>com.zenjava</groupId>
                    <artifactId>javafx-maven-plugin</artifactId>
                    <version>2.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>com.zenjava</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>2.0</version>
                <configuration>
                    <mainClass>sample.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>javafx</artifactId>
            <version>2.2</version>
            <systemPath>${java.home}/lib/jfxrt.jar</systemPath>
            <scope>system</scope>
        </dependency>
    </dependencies>
</project>

I'm using the JavaFX Maven Plugin to build the application. After running mvn clean jfx:jar everything seems fine, all builds succeed. But when I try to run the application I get the following error:

Exception in Application start method
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.javafx.main.Main.launchApp(Main.java:698)
        at com.javafx.main.Main.main(Main.java:871)
Caused by: java.lang.RuntimeException: Exception in Application start method
        at com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown So
urce)
        at com.sun.javafx.application.LauncherImpl.access$000(Unknown Source)
        at com.sun.javafx.application.LauncherImpl$1.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException: Location is required.
        at javafx.fxml.FXMLLoader.load(Unknown Source)
        at javafx.fxml.FXMLLoader.load(Unknown Source)
        at javafx.fxml.FXMLLoader.load(Unknown Source)
        at javafx.fxml.FXMLLoader.load(Unknown Source)
        at javafx.fxml.FXMLLoader.load(Unknown Source)
        at sample.Main.start(Main.java:15)
        at com.sun.javafx.application.LauncherImpl$5.run(Unknown Source)
        at com.sun.javafx.application.PlatformImpl$5.run(Unknown Source)
        at com.sun.javafx.application.PlatformImpl$4$1.run(Unknown Source)
        at com.sun.javafx.application.PlatformImpl$4$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at com.sun.javafx.application.PlatformImpl$4.run(Unknown Source)
        at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
        at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at com.sun.glass.ui.win.WinApplication.access$100(Unknown Source)
        at com.sun.glass.ui.win.WinApplication$3$1.run(Unknown Source)
        ... 1 more

After some rough debugging the trouble seems to be in the path I am loading my files from. After hardcoding the sample.fxml to a place on my hard drive, the application runs without any problems. Same goes for the current setup (seen above) when running the application from IntelliJ.

I feel like I have exhausted every resource (including StackOverflow, some very similar errors) but I just can't figure out what exactly is wrong.

回答1:

Make sure that your sample.fxml is in the src/main/resources/ directory (or a subdirectory). Then you can access the file like this:

Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("sample.fxml"));

Explanation: During the compile phase all resources and classes get copied to target/classes/. So your fxml file resides in this directory and your class in a subdirectory regarding its package name. If you call getClass().getResource("sample.fxml"); the file will be searched relative to the class file which will be this directory: target/classes/sample/.

Calling .getResource() on the classloader sets the relative search path to target/classes/ and therefore your file gets found.

P.S. You could also write:

Parent root = FXMLLoader.load(getClass().getResource("/sample.fxml"));


回答2:

As @Absurd-Mind already explained, maven will not copy any resource files (like fxml) which resides under the src directory.

If you want to keep the fxml files besides the java source files, you can use the maven resource plugin to copy them:

<build>
    ...
    <resources>
        <resource>
            <filtering>false</filtering>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.fxml</include>
            </includes>             
        </resource>
    </resources>
    ...
</build>


回答3:

I had the same issue with Intelij and Gradle.

Steps to fix:

1.Move file

sample.fxml

to path

\src\main\resources\fxml

  1. Set path on this file:

Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));



回答4:

For those who use gradle as their build system add this to your build.gradle file:

sourceSets.main.resources {
    srcDirs = ["src/main/java"]; //assume that your java classes are inside this path
    exclude "**/*.java"
}

Then clean and rebuild your project.

So what will it do? If you have a view.fxml inside your com.example.myfxapp package, after building your project it will exported to <build dir>/resources/com/example/myfxapp/view.fxml



回答5:

For me I had took care of following things -

  1. Make sure fxml file is placed where your main class resides. And then load it using this - (In my case, TechJFX.fxml is the file)

    FXMLLoader loader = new FXMLLoader(getClass().getResource("TechJFX.fxml"));
    
  2. Add opencv-*.jar to your project folder (In my case opencv-300.jar)

  3. Add the jar to the build path using

Right click on the project folder -> Build Path -> Configure Build Path -> Libraries Tab -> Add External JARS and locate the jar

Also, under Order and Export -> Tick opencv-300.jar and JRE System Library(if not already ticked)

  1. Copy opencv_java*.dll (In my case opencv_java300.dll) to the same location where you jar is in the project folder.

  2. Add the following method to your main class

     static{ 
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
       }
    
  3. Done.

Hope this helps someone facing similar issue.