18

I need to load a property file from the jar. The jar is included in war file. Here is the structure

ROOT.war
  WEB-INF
     lib
       my.jar

here my.jar has following structure

my.jar
  com
    test
      myservlet.class
  WEB-INF
    test.property

Now I have written following code in one of my servlet as follows:

InputStream stream = getServletContext().getResourceAsStream("/WEB-INF/test.properties");
Properties prop = new Properties();
prop.load(stream );

but above code I got stream as null. If I put the property file in ROOT.war/WEB-INF it works fine. I have fair idea that if path in getResourceAsStream starts with '/' than it search resource in context root. But how can I read resource which lies in a jar which again found in WEB-INF/lib of root application?

Thanks & Regards, Amit Patel

Amit Patel
  • 15,609
  • 18
  • 68
  • 106

3 Answers3

38

Put it in root of the JAR and get it by context classloader instead of servletcontext.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("test.properties");
// ...

The /WEB-INF folder convention is specific to WAR files, not to JAR files. Get rid of it. If you really need a separate JAR folder which is to be part of the classpath, use /META-INF instead.

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("META-INF/test.properties");
// ...
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • ...or leave things as they are and use "WEB-INF/test.property". – Brett Kail Jan 03 '11 at 15:33
  • @bkail, can also, but there's no reason to use `WEB-INF` folder since that isn't ever going to be accessible by servletcontext. It also doesn't make sense to put a WAR-specific folder convention in a plain vanilla JAR file. – BalusC Jan 03 '11 at 15:37
  • Agreed, did not mean to imply your answer was incorrect. Just providing the OP another option in case changing the JAR structure is difficult or not possible for some reason. – Brett Kail Jan 03 '11 at 15:39
  • Another interesting point would be that `getFile` sometimes (in case of WildFly) returns an incorrect path so you have to use `getResourceAsStream`. – CSchulz Sep 16 '15 at 15:57
  • I recommend reading stackoverflow.com/a/2161583/2412477 since it goes into more detail on the issue. That is the top answer of the question, that this post is a [duplicate] of. This question, however, was worded better for my particular problem, so that's how I got here =) – Stephan Henningsen Oct 03 '18 at 07:36
6

You can access any resource on the standard classpath from a given instance

this.getClass().getResourceAsStream("name");

for example from your "myservlet" class (Bad naming).

getServletContext().getResourceAsStream() accesses content in the context of the web application base directory.

It seems bad style to incldue a WEB-INF directory in a jar - you would cause confusion. Can't you find a better name?

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
mtraut
  • 4,720
  • 3
  • 24
  • 33
2

This is what I have found and it worked for me. The help provided by @BalusC worked for me. I have collated what I have found and how I have verified that it is working.

I have got a maven project with following structure as shown below

project structure

Now when I build this project; the jar looks like

enter image description here

and here queries.properties moves under "META-INF" folder. Now if this jar has a class which is trying to utilize this property file using Thread.currentThread().getContextClassLoader().getResourceAsStream("queries.properties")

thinking that the same file can still be accessed under resources folder as shown in project structure, that is wrong. The correct way is to access via META-INF folder

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream is = classLoader.getResourceAsStream("META-INF/queries.properties");

How did I verified

Just create a simple java project and include the jar you have just created into its build path and create an instance of class which is having ClassLoader statements as mentioned above. Your code in this new java project should look like

public static void main(String[] args){
        new Queries();
    }

where Queries is a class in jar you have just included in your build path.

Rupesh
  • 2,627
  • 1
  • 28
  • 42