r/javahelp Feb 22 '22

Solved getResourceAsStream() == null when run from JAR

hello!

I have line of code such as this:

final Image roll_bg = new Image(this.getClass().getResourceAsStream("../resources/roll_bg.png"));

in IDE image is found and is rendered on canvas as expected, when exported to JAR, run ends with error. For JAR runs then, I did most hacky thing possible to extract what is wrong like so:

URL path = App.class.getResource("App.class");
if (path.toString().contains("jar")) {
    PrintStream ps = new PrintStream("./log.txt");
    System.setErr(ps);
    System.setOut(ps);
    System.out.println("Stream OUT: rerouted!");
    System.err.println("Stream ERR: rerouted!");
}

and log.txt says that InputStream is null (presumably did not found resource)

Caused by: java.lang.NullPointerException: Input stream must not be null
    at javafx.graphics/javafx.scene.image.Image.validateInputStream(Unknown Source)
    at javafx.graphics/javafx.scene.image.Image.<init>(Unknown Source)
    at com.engine.Engine.<init>(Engine.java:32)
    at com.engine.Engine.get(Engine.java:94)
    at com.App.start(App.java:60)

most online resources point to this method being able to reach resources from within JAR, does not work for me though. Thank you for any help offered!

4 Upvotes

24 comments sorted by

View all comments

1

u/wildjokers Feb 22 '22 edited Feb 22 '22

When accessing it via getResourceAsStream you are loading the resource from the classpath. You want the resource (in your case an image) to be on the classpath at the same location regardless if you are running from your IDE or from a jar file. In your case the path is not correct in the jar file.

Do you have a resources directory in your jar file? Most build tools by default will copy the contents of the resources directory directly to the root of the jar file (both maven and gradle will do this). So I highly doubt you have a resources directory in the jar file. Also the relative path ../ would also be odd. Best to access it via an absolute path from the root of the jar.

So the correct path to your image will be getResourceAsStream("/roll_bg.png").

Then in your IDE you want the contents of the resources directory on the classpath but not the resource directory itself. I am not sure which IDE you are using but IntelliJ will happily configured itself from a maven or gradle build. And since maven and gradle put the contents of the resources directory on the classpath it will work from the IDE too.

By the way this is a very common problem for beginners.

1

u/sparkless12 Feb 23 '22

I do have resources directory, I am not using any build tools like Maven or Gradle. Problem solved. And no, your path did not work.

1

u/wildjokers Feb 23 '22

Obviously my path did not work of you have a resources sub-directory in your jar. You gave us no details at all about the layout of your jar so I could only assume you were using a proper build tool to build it.

If you build a jar some other hacky way that doesn’t build a jar according to expected conventions then you should expect to have to do unconventional things to make your code work.

If you ask a question about not being able to load a resource from a jar do us all a favor and actually give us details about the layout of your jar.

Your response here comes off as very rude to someone that took time out of their day to try to help you out. I have many years experience (18+) writing desktop apps with Java and I know exactly how to write code that loads resources from the classpath so that the path is the same when running from an IDE and when running as a jar file.

FWIW, you should not be putting the resources directory in your jar file. You should only be putting the contents of the resources directory. This is the expected convention. If you use a proper build tool it will handle this for you.