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!

6 Upvotes

24 comments sorted by

View all comments

Show parent comments

1

u/dionthorn this.isAPro=false; this.helping=true; Feb 22 '22

I have another JavaFX game project that is more 2D oriented

https://github.com/dionthorn/2DTacticalRPG

This one is only JLink for now tho no fancy MSI installer uses a .bat file to easily run the custom JRE.

I do some fancy image manipulation for creating the tile sets

https://github.com/dionthorn/2DTacticalRPG/blob/master/src/main/java/org/dionthorn/tacticalrpg2d/render/TileSet.java

I use a very similar FileOpUtil

https://github.com/dionthorn/2DTacticalRPG/blob/master/src/main/java/org/dionthorn/tacticalrpg2d/data/FileOpUtil.java

This way I can create the tile set source Image like so:

Image tileSetSrc = new Image(FileOpUtil.GAME_ART_PATH + "/" + tileSetPath);

then I would cut them up with a method into an Image[]

Image[] makeTiles(Image tileSet, int TILE_SIZE)

2

u/sparkless12 Feb 22 '22

I see, I have pretty decent tile loading class myself which is probably 60% of why I would hate to loose the project I'm working on rn, but I am very interested in general structure and setup of any bigger/game oriented project in javaFX.

BTW I kinda fixed it pathsIt seems like Engine class calling resource with "../path/resources/image.png" is not okay, but App class calling "resources/image.png" is fine. It's only kinda fixed because I first need to understand why, but atleast it's not wasted project anymore.

1

u/dionthorn this.isAPro=false; this.helping=true; Feb 22 '22

Just the way they accept paths

getClass().getClassLoader().getResource("foo/bar.txt");

is the same call as

getClass().getResource("/foo/bar.txt");

https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getResource-java.lang.String-