Load properties file in JAR?

JavaMaven 2ResourcesPropertiesClassloader

Java Problem Overview


I'm having trouble when one of the jars that my web app depends on tries to load a properties file from within the jar. Here is the code in the jar.

static
{
	Properties props = new Properties();
    try 
    {
		props.load(ClassLoader.getSystemResourceAsStream("someProps.properties"));
	} catch (IOException e) 
	{
		e.printStackTrace();
	}
	someProperty = props.getProperty("someKey");
}

The properties file is in my "src/main/resources" directory of the Maven project. When I run this code from my junit test in Eclipse, it executes just fine. When the project is built with Maven into a jar, and included as a dependency in my web app, it fails to locate the properties file. I know that the properties file is at the base directory of the depended on jar, I don't know how to fix this.

Java Solutions


Solution 1 - Java

The problem is that you are using getSystemResourceAsStream. Use simply getResourceAsStream. System resources load from the system classloader, which is almost certainly not the class loader that your jar is loaded into when run as a webapp.

It works in Eclipse because when launching an application, the system classloader is configured with your jar as part of its classpath. (E.g. java -jar my.jar will load my.jar in the system class loader.) This is not the case with web applications - application servers use complex class loading to isolate webapplications from each other and from the internals of the application server. For example, see the tomcat classloader how-to, and the diagram of the classloader hierarchy used.

EDIT: Normally, you would call getClass().getResourceAsStream() to retrieve a resource in the classpath, but as you are fetching the resource in a static initializer, you will need to explicitly name a class that is in the classloader you want to load from. The simplest approach is to use the class containing the static initializer, e.g.

[public] class MyClass {
  static
  {
    ...
    props.load(MyClass.class.getResourceAsStream("/someProps.properties"));
  }
}

Solution 2 - Java

For the record, this is documented in How do I add resources to my JAR? (illustrated for unit tests but the same applies for a "regular" resource):

> To add resources to the classpath for > your unit tests, you follow the same > pattern as you do for adding resources > to the JAR except the directory you > place resources in is > ${basedir}/src/test/resources. At > this point you would have a project > directory structure that would look > like the following: > > my-app > |-- pom.xml > -- src > |-- main > | |-- java > | | -- com > | | -- mycompany > | | -- app > | | -- App.java > | -- resources > | -- META-INF > | |-- application.properties > -- test > |-- java > | -- com > | -- mycompany > | -- app > | -- AppTest.java > -- resources > -- test.properties > > In a unit test you could use a simple > snippet of code like the following to > access the resource required for > testing: > > ... >
> // Retrieve resource > InputStream is = getClass().getResourceAsStream("/test.properties" ); >
> // Do something with the resource >
> ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndyView Question on Stackoverflow
Solution 1 - JavamdmaView Answer on Stackoverflow
Solution 2 - JavaPascal ThiventView Answer on Stackoverflow