Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java classloader not able to find resource in jar file

I have a runnable jar file which is not able to access my resources which reside outside of the default src directory. Based on my understanding from What is the difference between Class.getResource() and ClassLoader.getResource(), I should be able to access root/res/img/img1.png (see folder setup below) by using the following getResourceFile function:

public class Foo {

    private static final ClassLoader CLASS_LOADER = Foo.class.getClassLoader();

    public static File getResourceFile(String relativePath) {
        // Since I'm using getClassLoader, the path will resolve starting from 
        // the root of the classpath and it'll take an absolute resource name
        // usage: getResourceFile("img/img1.png")
        // result: Exception in thread "main" java.lang.NullPointerException
        return new File(CLASS_LOADER.getResource(relativePath).getFile());
    }
}

folder setup:

root/
    src/
        foo/
            bar/
    res/
        img/
            img1.png
        audio/
            audio1.wav

The problem arises when I try to execute the jar executable itself. However, the strange thing is that I was not able to replicate this through eclipse IDE which was actually able to resolve the path correctly. I have added the resource directory to the build path via (Project -> Properties -> Java Build Path -> Add Folder) so Java should be able to find the resource folder at runtime.

Is there something I'm missing in terms of generating the jar file? When unpacking the jar file everything seems to be in order with the img and audio directories being in the root (given the above initial folder setup):

foo/
    /bar
img/
    img1.png
audio/
    audio1.wav
like image 728
Alan Avatar asked Jan 06 '23 11:01

Alan


1 Answers

Files can only be used to represent actual files in your filesystem. And once you package your files into a JAR, the resource (img/img1.png) is not a file anymore, but an entry in the JAR file. As long as you use the folder structure from within Eclipse, the resources are individual files so everything is fine.

Try this:

System.out.println(CLASS_LOADER.getResource(relativePath));

It will print a URL, but it will not be a valid path to a file in your file system, but to an entry within the JAR file.

Usually, you will only want to read a resource. In that case, use getResourceAsStream() to open an InputStream.

like image 195
Tobias Avatar answered Jan 13 '23 09:01

Tobias