getResource() vs. getResourceAsStream()

TechJavaResources

Today I stumbled upon a problem which was easy to fix but quite interesting to see. The task was to find a way in Java to read a file from the classpath (src/resources/filename.png). As easy as it sounds, as easy it is. Using Objects.requireNonNull(getClass().getClassLoader().getResource("filename.png")) will return a URI which in turn can be easily transformed into a File object. Testing it in the IDE works fine. Problem solved right?

Sure, you guessed it, it was not solved at all. While it works inside the IDE, it did not work anymore when executing the packaged .jar file. So, searching for a solution gave me a 🤦 as it is actually obvious. When executing the program in my IDE, all the resources are in the correct place and in the correct format. However, using Maven to package the project to a working .jar file will move all the resources to the root folder of the jar. In addition, the resulting jar is a byte stream instead of a collection of standard files. The jar itself is the only file.

So, how to fix it? Well, now that we know this fact, we are using getResourceAsStream() as displayed in the following snippet:

Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream("filename.png"))

This approach has no problem working in the IDE and as jar. In fact, it is also easier to integrate this implementation into the rest of the code because most of the other methods can operate with InputStreams right away such as ImageIO.read(inputStream) which I used to store the image as BufferedImage.