0

I'm currently trying to start coding an app with IntelliJ and JavaFX, I have the following code :

package main.gui;

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

import java.net.URL;

public class MainMenu extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("hello-view.fxml"));
        URL url = getClass().getResource("hello-view.fxml");
        System.out.println("URL = " + url);
        Parent root = FXMLLoader.load(url);
        Scene scene = new Scene(root,1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

}

My file structure :

  • src/main/gui/MainMenu.java
  • src/main/gui/hello-view.fxml

And I get this exception :

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:1082)
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.NullPointerException: Location is required.
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3324)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3287)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3255)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3227)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3203)
    at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:3196)
    at main/main.gui.MainMenu.start(MainMenu.java:13)
    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)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    ... 1 more

It outputs : URL = null

I've tried a lot of stuff that I've found on this site but without success...

Thank in advance for your help :)

  • Your file should be under `src/main/resources` in order to be loaded using the `getResource()` method. Also, use `getClass().getClassLoader().getResource()` instead of simply `getClass().getResource()` – Matteo NNZ Jun 08 '22 at 22:55
  • 3
    @MatteoNNZ That's only a convention used by e.g., Maven and Gradle. The OP makes no mention of using either build tool, only IntelliJ. And in their case `main` seems to be a _package_ with `src` being the "sources root". – Slaw Jun 08 '22 at 23:00
  • 2
    @MatteoNNZ Also, why insist the OP use `ClassLoader#getResource(String)` instead of `Class#getResource(String)`? The latter will work just as well; plus, in the OP's case, they can use a relative resource name (instead of absolute, though I prefer using absolute anyway). And a nice bonus is that the latter will work better with the JPMS world (if your code is modular), especially when loading a resource from within the same module as the class (i.e., no need to `opens` the resource package unconditionally). – Slaw Jun 08 '22 at 23:08
  • @Slaw all you're saying is theoretically true. But I've been around long enough to state empirically that 99.99% of times this problem is raised, it ends up resolved by the combination of the two things I mentioned above. Let's see what OP says, I'm ready to bet it will work ;) – Matteo NNZ Jun 08 '22 at 23:14
  • P.s. I've posted a comment instead of an answer just because mine was an empirical observation, not a theoretical response. I have no theoretical evidence to prove that it should work, though I'm really confident it will. – Matteo NNZ Jun 08 '22 at 23:16
  • 3
    @MatteoNNZ Yes, I've seen such changes fix the problem as well. But whether using `ClassLoader#getResource(String)` or `Class#getResource(String)`, it really should not matter as long as the passed-in argument is correct for the given API (especially with non-modular code). I only commented because I find it strange that people often suggest switching to the former instead of just fixing the use of the latter :). My issue with the `src/main/resources` suggestion is that the OP's code seems to run without using `src/main/java`. Though they have `src/main`, so perhaps things got messed up. – Slaw Jun 08 '22 at 23:38
  • 1
    @DIEGOIGLESIAS Please add information about your environment and project structure. I couldn't reproduce your problem from my guess as to how you have your project set up. How did you create the project in IntelliJ? Are you using Gradle? Maven? Neither? If you _are_ using a build tool, how are you executing the project? Via the build tool, or via IntelliJ's own build system? A [mre] would be best. And see if [How do I determine the correct path for FXML files, CSS files, Images, and other resources needed by my JavaFX Application?](https://stackoverflow.com/questions/61531317/) helps at all. – Slaw Jun 08 '22 at 23:41
  • You are using idea, just use the [new JavaFX project wizard](https://www.jetbrains.com/help/idea/javafx.html). It will create a new project with an appropriate build system, layout and sample code, with everything in the expected location and your problem with resource location will just go away. – jewelsea Jun 08 '22 at 23:48
  • @jewelsea Suggesting that the OP change their IDE is taking a hammer to crack a nut. All he needs to do is deploy his application correctly. – user207421 Jun 09 '22 at 00:12
  • @MatteoNNZ Looks like your suggestions worked ;) – Slaw Jun 09 '22 at 00:24
  • 4
    Also, `getClass().getClassLoader().getResource()` is double wrong. [A] do not use `.getClassLoader()` (it is pointless typing, it deletes the ability to go relative to type, if you want to go relative to root, just call `.getResource` on a class and stick a slash in front, and `.getClassLoader()` can return null in exotic circumstances, and [B] use `MyClass.class`, not `getClass()` - `getClass()` breaks when subclassing under certain conditions. – rzwitserloot Jun 09 '22 at 01:08
  • @Slaw yep, another 0.01% added to the stats I was mentioning in my previous comment :) – Matteo NNZ Jun 09 '22 at 06:12
  • @user207421 The question mentioned that IntelliJ was used, I just offered advice on how to use it. – jewelsea Jun 09 '22 at 07:09
  • Ultimately, all that is really important is what is in the *build*, not the *source*. So there are two things needed to understand to make this work reliably: 1. how `getResource(...)` loads resources from the *classpath* (i.e. the content of the build) and 2. how your build tool (Maven, or the IDE, etc.) deploys resources from the source folder to the build (folder or jar file) at build time. Many of the suggestions in this thread are making guesses based on "empirical evidence" about how your build tool might be behaving. Instead, try to understand what it is doing. – James_D Jun 09 '22 at 13:52
  • @James_D just a little comment. OP posted a question without precising the build system, nor the project structure (except for the two files he needed). When I talked about "empirical evidence" I didn't do it because I didn't try to understand what is doing. I did try it, and I did get it. About 6 years ago. So yesterday I opened SO, saw this question coming over again, saw IntelliJ + JavaFx, I knew it was maven and I knew it would have solved the issue. I wanted to unblock the guy quickly (which happened indeed), didn't want to document how it works else I would have posted an answer – Matteo NNZ Jun 09 '22 at 20:44
  • @MatteoNNZ You only *know* it solves the issue if you know the Maven configuration, which you don’t. If the OP is using the default build config, then this will work, but in other configs it might not. So, technically, you’re guessing that that’s the case. If the purpose of this site were to act as a free help desk, then perhaps “quickly unblocking” the OP is useful, but that’s not what this site is for. – James_D Jun 09 '22 at 20:53
  • @James_D stack overflow is two things to me. An excellent documentation hub (that I consult almost daily) and a kind of help desk (specific problems, not really common, hard to describe for which you get kind help by peers). This question is neither. How to get resources is documented everywhere (even on SO). Plus, the question is not clear (not enough detail needed). If we really wanted to stick to what the site is for, the question should be closed as duplicate or unclear. But again, to my eyes, SO is a documentation hub, but not only. – Matteo NNZ Jun 09 '22 at 20:56
  • P.s. you're right, of course. If the build wasn't maven, my comment was wrong. But it's enough to read the code to understand OP is on his first JavaFx project with an IntelliJ community by default on which he used the default project wizard. The odds that the build system wasn't maven was really low, so I just shot a comment out of the dark, I clearly didn't mean to explain how it worked (cause again, if I did, I would have taken the time to look for the answer which already explains this and mark the question as duplicate) – Matteo NNZ Jun 09 '22 at 21:01

1 Answers1

0

To add a little more detail : I'm using Maven and I created the project with the JavaFX project creation tool provided with IntelliJ.

I made it work by simply putting my fxml file into a ressources folder (src/main/resources) as suggested by @MatteoNNZ. I tweaked a little bit the code to have the following :

package main.gui;

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

import java.net.URL;

public class MainMenu extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        URL url = getClass().getClassLoader().getResource("hello-view.fxml");
        System.out.println("URL = " + url);
        Parent root = FXMLLoader.load(url);
        Scene scene = new Scene(root,1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

}

Obviously it could be simplified like this :

@Override
    public void start(Stage stage) throws Exception {
//        URL url = getClass().getClassLoader().getResource("hello-view.fxml"); |
//        System.out.println("URL = " + url);                                   | Remove these 3 lines
//        Parent root = FXMLLoader.load(url);                                   |
        Scene scene = new Scene(FXMLLoader.load(getClass().getClassLoader().getResource("hello-view.fxml")),1920,1080);
        stage.setTitle("Hello!");
        stage.setScene(scene);
        stage.show();
    }

but it is very ugly.

Thank you everyone for your help and very quick answers :) .

  • 4
    Note, if you're using Maven, then your source files (i.e., the `*.java` files) should all be under the `src/main/java` directory. Any directories under `src/main/java` would be packages. You might want to fix that as well. – Slaw Jun 09 '22 at 00:21
  • Indeed as @Slaw mentioned, if you are using IntelliJ project wizard (which I was sure about) you should stick to the structure they suggest, source files under Java (so they become packages) and resource files under resources – Matteo NNZ Jun 09 '22 at 06:14
  • 1
    For more info on project structure for Maven based projects, see the [standard directory layout](https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html), also described at [baeldung](https://www.baeldung.com/maven-directory-structure), to better understand your build tool study [maven getting started](https://maven.apache.org/guides/getting-started/index.html) and [maven basics](https://www.baeldung.com/category/maven/tag/maven-basics/) and [using maven in your ide](https://www.jetbrains.com/help/idea/maven-support.html). – jewelsea Jun 09 '22 at 17:36