Of the 12 or so Java libraries used in this site, 6 of them by default have their configuration files in the CLASSPATH:
- log4j (log4j.properties / log4j.xml)
- commons-logging (commons-logging.properties)
- XWork (xwork.xml)
- WebWork (webwork.properties, validators.xml plus all the <action>-validator.xml)
- OSCache (oscache.properties)
- iBATIS (the sql map configuration and definition)
Various resource bundle also litter the CLASSPATH, thanks mainly to WebWork action messages and global resource bundle. Enough of that for me, time to end that incestuous relationship, stop wasting time with .cvsignore and svn:ignore: I want Java classes in the CLASSPATH and nothing else. I could convince at least log4j and Ibatis to look elsewhere:
- log4j has PropertyConfigurator.configureAndWatch(), where the argument is the full path of WEB-INF/config/log4j/log4j.properties
- Ibatis has SqlMapClientBuilder.buildSqlMapClient(), where the argument is a java.io.Reader from the full path of WEB-INF/config/ibatis/sqlMapConfig.xml (nice side effect, I can freely reload my Sql map definitions at runtime)
For resource bundles I now use a database, a simple table with (key, language, message) and a class that implements ResourceBundle, no more .properties and native2ascii to deal with.
As you see, I've started to use WEB-INF/config and subdirectories, whose full paths are determined via ServletContext.getRealPath("/") + "/WEB-INF/config". The benefits:
- the files won't be served to HTTP clients
- very easy to put under source control, no gymnastics with .cvsignore or svn:ignore required
There is one disadvantage, it won't work if the web application runs from a compressed WAR file: my guess that WEB-INF/classes became a popular dumping ground because other than Thread.getContextClassLoader().getResource() there is no portable way of reading files in a web application. How many web application actually run from a compressed WAR file? What's the rationale for having it in the Servlet spec?