Search code examples
javaresourcesclassloader

getResourceAsStream fails under new environment?


Hallo,

i have following line of code:

InputStream passoloExportFileInputStream = getClass().getClassLoader().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");

and i know that jar with com/thinkplexx/lang/de/general.xml is in classpath.

It worked under "previous environment", which is maven2 build.

Now, i evaluate maven3 and it doesn't work! I know, that if i change the code to be:

InputStream passoloExportFileInputStream = getClass().getClassLoader().getResourceAsStream("com/thinkplexx/lang/de/general.xml");

it works great (i just removed the first slash from the resource path).

Btw, i use Linux. First slash in path normally means "from the root directory", so if this logic is sound for java resource loading as well, first example should never have worked!?

Questions: is something wrong with the first code sample, i.e. with /com/ and not com/? Is it just bad code or it means something different?

thank you!


Solution

  • It depends on how you are getting the resource. When you use a ClassLoader as in:

    InputStream stream= getClass().getClassLoader().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");
    

    The leading '/' is meaningless. So, the correct form is "com/thinkplexx/lang/de/general.xml".

    If, instead you use a 'Class', as in:

    InputStream stream= getClass().getResourceAsStream("/com/thinkplexx/lang/de/general.xml");
    

    You get a different behavior. The Class.getResourceAsStream will consider classes without a leading '.' to be relative to the package containing the class. Resources specified with a leading '.' are absolute, or resolved relative to the root of the jar.

    So, if this is a reference to com.example.SomeThing, then the expected behavior is:

    getClass().getResourceAsStream("/a/b/c.xml")  ==> a/b/c.xml
    getClass().getResourceAsStream("a/b/c.xml")  ==> com/example/a/b/c.xml
    getClass().getClassLoader().getResourceAsStream("a/b/c.xml")  ==> a/b/c.xml
    getClass().getClassLoader().getResourceAsStream("/a/b/c.xml")  ==> Incorrect
    

    Maven2 was being lax and allowing the last form.