views:

66

answers:

4

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?

+1  A: 

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");
    

The 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.

BalusC
not in this case
unbeli
@unbeli: what do you mean?
Roman
@unbeli: good luck when you distribute it as JAR then :)
BalusC
@BalusC 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.
unbeli
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.
unbeli
@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.
BalusC
@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.
BalusC
+3  A: 

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.

Jesper
thanks, this works.
Roman
+3  A: 

How about...

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

That properties file should automatically resides in WEB-INF/classes directory.

limc
this will prepend the package of the current class. You need the leading slash to avoid that.
unbeli
A: 

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.

Gelvis