How to read properties file in web application? [duplicate]
Asked Answered
A

3

26

Properties file location is WEB-INF/classes/auth.properties.

I cannot use JSF-specific ways (with ExternalContext) because I need properties file in a service module which doesn't have a dependency on a web-module.

I've already tried

MyService.class.getClassLoader().getResourceAsStream("/WEB-INF/classes/auth.properties");

but it returns null.

I've also tried to read it with FileInputStream but it requires the full path what is unacceptable.

Any ideas?

Adeliaadelice answered 1/7, 2010 at 18:38 Comment(0)
O
54

Several notes:

  1. You should prefer the ClassLoader as returned by Thread#getContextClassLoader().

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    

    This returns the parentmost classloader which has access to all resources. The Class#getClassLoader() will only return the (child) classloader of the class in question which may not per se have access to the desired resource. It will always work in environments with a single classloader, but not always in environments with a complex hierarchy of classloaders like webapps.

  2. The /WEB-INF folder is not in the root of the classpath. The /WEB-INF/classes folder is. So you need to load the properties files relative to that.

    classLoader.getResourceAsStream("/auth.properties");
    

    If you opt for using the Thread#getContextClassLoader(), remove the leading /.

The JSF-specific ExternalContext#getResourceAsStream() which uses ServletContext#getResourceAsStream() "under the hoods" only returns resources from the webcontent (there where the /WEB-INF folder is sitting), not from the classpath.

Osculum answered 1/7, 2010 at 18:40 Comment(5)
@unbeli: good luck when you distribute it as JAR then :)Osculum
@Osculum you edited your answer, before it recommended only to use the context class loader. It is obvious, that the issue is not the wrong classloader, but the wrong path.Passport
Besides that: if the resource belongs to the class and is not an external configuration, you should use only Class#getResource() / getResourceAsStream(). Class#getClassLoader() won't return any child class loaders. Context class loader does not have access to all resources.Passport
@unbeli: you misunderstood me. I was saying like that using ClassLoader#getResourceAsStream() is more recommend than using ExternalContext#getResourceAsStream(). Also see the edit history. I removed it because the OP mentioned that it was not an option at any way (which I overlooked). I'd appreciate if you remove the downvote.Osculum
@unbeli: it's however useful if you want to externalize the resource and/or want to be able to override it without rebuilding/redeploying the whole webapp on every edit of the file.Osculum
P
8

Try this:

MyService.class.getClassLoader().getResourceAsStream("/auth.properties");

Reading files with getResourceAsStream looks on the classpath to find the resource to load. Since the classes directory is in the classpath for your webapp, referring to the file as /auth.properties should work.

Percheron answered 1/7, 2010 at 18:41 Comment(0)
S
5

ResourceBundle (http://download.oracle.com/javase/6/docs/api/java/util/ResourceBundle.html) resolve most of the problems with a relative/absotule path for Properties Files.

It uses the the Resource class and point it to a Dummy Class to make reference to a properties file.

For example:

  1. You a have file called MAINProperties.properties and inside it there is a property: mail.host=foo.example.com
  2. Create a Dummy Class called MAINProperties without nothing.
  3. Use the following code:

    ResourceBundle.getBundle("com.example.com.MAINProperties").getProperty("mail.host")

And That's it. No InputStreams Required.

P.D. Apache Commons has a Library Called Apache Commons Configuration that has a lot of capabilities (reloadable files, multiple domain types) that could be used in combination of the above.

Schriever answered 13/9, 2010 at 21:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.