Skip to content
Advertisement

Intellij can’t read images in resources subfolder

So I have a maven project in intellij and I want to load images from the resources folder. It works perfectly for files that are directly in resources/. However, files that are in subfolder (for example resources/images/) are not found.

In this example, logo.png is correctly loaded while logo1.png is not found :

var img2 = new Image("logo1.png");
var img = new Image("images/logo.png");

I could put all my files directly in resources, but it would be all disorganized…

Here’s the error I get when loading images/logo.png :

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:564)
    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:564)
    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:832)
Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
    at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1125)
    at javafx.graphics/javafx.scene.image.Image.<init>(Image.java:618)
    at org.example/org.example.App.start(App.java:25)
    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:391)
    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
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
    at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1117)
    ... 11 more
Exception running application org.example.App

Process finished with exit code 1

Advertisement

Answer

var img2 = new Image("logo1.png");

This code is just wrong, that’s not how you load resources.

This is how you do it:

var img2 = new Image(TheClassThisCodeIsIn.class.getResource("logo1.png").toString());

The new Image(string) constructor takes as argument a URL, and logo1.png is not one of those.

In particular you are looking to load images from the exact same place java is loading your app’s class files, which is done with someClassInstanceThatIsUsedForContext.getResource. The best context to use is no doubt the class you’re in, hence, TheClassYouAreIn.class, which gets you that class instance. The getResource method returns a URL.

Note that the above construct is using relative paths: That code will look for a resource named logo1.png in the same place that TheClassThisCodeIsIn.class is located, even if it is in a jar file, dynamically created, or loaded over the network. In other words, if you have:

package com.foo.sashimisAwesomeApp;

public class MyApp {}

Then MyApp.class.getResource("hello.png") will look for com/foo/sashimisAwesomeApp/hello.png, because the class file for MyApp is at com/foo/sashimisAwesomeApp/MyApp.class. This means you need to match the package structure (That com/foo/sashimisAwesomeApp part) in your resource folder in your project directory structure. If you prefer to go from the ‘root’ of resources, include a leading slash: MyApp.class.getResource("/images/icon.png") will look in /images/icon.png in the jar file that also contains /com/foo/sashimisAwesomeApp/MyApp.class.

NB: Sidenote to the author of javafx’s Image class: Geez, what a disaster. That API should obviously have taken in a URL or URI or have a static constructor to load off of classpath instead of this mess.

6 People found this is helpful
Advertisement