February 24, 2004
Locating the configuration files for my J2EE app

Arrrrrgh! I just can't believe that this is hard! (Or perhaps it's just me that finds this hard. That's not so difficult to believe.)

OK, so, the J2EE application we are working on needs some configuration, so I've monkied up a quick Digester based configuration file reader. That should have been the hard bit, but it's been a piece of cake. Digester is great!

But now I need to get it to read the configuration file from within my J2EE application. So where do I put this file, and how do I tell Tomcat (or whatever) where to look for it?

I've currently got this file in WEB-INF/config.xml, which feels right. But Tomcat can't find it given just this as a file path. I suppose that I need to prepend the document root to this - but how do I find that? (I'm currently trying to read this file in a ServletContextListener's contextInitialized method.)

Naturally, I'd rather not use anything Tomcat specific if I can help it. But I did try this:

final ProxyDirContext proxyDirContext = (ProxyDirContext) servletContext.getAttribute("org.apache.catalina.resources");
final String docBase = proxyDirContext.getDocBase();

But unluckily (or perhaps luckily) this didn't work. It *would* work from a Servlet, I think, but the org.apache.catalina.resources context attribute doesn't seem to exist as the context is initialised.

Arrrrrgh!

Posted to Java by Simon Brunning at February 24, 2004 12:49 PM
Comments

Thestandard approach is to put it in the root of your classes - so for a webapp put it in WEB-INF/classes/. You can then access it by calling Class.getResource("filename.xml") to give you a URL to the file, or Class.getResourceAsStream("filename.xml") to return an InputStream.

Posted by: Sam Newman on February 24, 2004 01:23 PM

You could try jconfig (http://www.jconfig.org/) if you are running on jboss. They seem to have a pretty good solution for this.

Posted by: Tom Ayerst on February 24, 2004 01:47 PM

Thanks, Sam.

final ServletContext context = servletContextEvent.getServletContext();
final URL configFileURL = context.getResource("/WEB-INF/config.xml");
final InputStream configFileStream = configFileURL.openStream();

This works a treat.

Posted by: Simon Brunning on February 24, 2004 02:08 PM

funny I thought the standard approach was the "Preferences API" ?

http://java.sun.com/j2se/1.4.2/docs/guide/lang/preferences.html

But maybe things have changed?

jez.

Posted by: jez on February 24, 2004 03:30 PM

The preferences API will rely on storing things 'per user'. On windows it uses the registry, on linux the $HOME area - it will be using files outside the scope of the web application itself. Beyond the fact that the security settings of the web application might not allow access to the filesystem outside the web applications structure, its considered bad practise to rely on files in this way.
The preferences API works like a dream for desktop applications though.

Posted by: Sam Newman on February 24, 2004 03:38 PM

Propbably didn't explian myself too well here. The configuration file is required for the program to work, and is not something an end user should have to edit. As such the file should be encapsulated within the web application WAR file and not exposed to user editing.

Posted by: Sam Newman on February 24, 2004 03:49 PM

The preferences API allows both USER and GLOBAL preferences. And provides an interface that can be satisfied by any implementation. Even one that matches the stricter security constraints in some web containers. But I suppose, unless someone has created an implementation of the preferences interfaces already (for use within WAR contexts), you might prefer the solution Sam has already mentioned. Then again, I guess going out to get prefs is probably an anti-pattern now anyways. Perhaps we should have "preference injector" as a sub-case of "dependancy injector" or "type3 IoC", i.e. pass in the prefs in the constructor to your MVC actions...

Posted by: jez on February 24, 2004 07:06 PM

Sam is right - put it in your classes directory and use getResource()/getResourceAsStream(). Be careful of your classloaders, though: Thread.currentThread().getContextClassLoader().getResourceAsStream(filename); is good.

Posted by: Nick Lothian on February 26, 2004 11:20 AM
Post a comment
Name:


Email Address:


URL:



Comments:


Remember info?