Tuesday, July 12, 2005

Location independent loading of properties

Heres another little douzie that been slapping me across the face all day.

When writing and deploying code you don't want to have absolute paths listed for config files, resources etc, as these will invariably lead to problems when moving the application to another server.

Normally with java this entails creating a deployment directory, and including within it all classes and resources that you may need. You then load all files and properties using the deployment directory as the root.

The question then arises how do you access these properties.

For example with properties files the initial way one thinks of to load properties is as follows


FileInputStream inputStream = new FileInputStream("");
Properties prop = new Properties();
prop.load(inputStream);


The problem with this is that the is an absolute value, which knows nothing of the deployment directory that you may be running from.

The solution is to use one of the following


Class.getResourceAsStream() or
ClassLoader.getResourceAsStream()


The funny thing is that for me sometimes the first method works (e.g. when run from within Eclipse), and the 2nd one fails. Sometimes (from with tomcat) the first one fails and the 2nd one works.

In fact initially I had posted to use the 2nd method after spending a few hours tracking down why my program worked in Eclipse but failed in tomcat. It was only a day later that I discovered that the 2nd method (which works in tomcat) doesn't work in eclipse.

So now I have this slightly ugly construct to try and get around the problems

/**
* The name of the properties files. N.B. the "/" at the start means it is an absolute
* package, not a relative path from this package.
* Default propertuies location /resources/rsi.properties in the classpath may be
* overridden by setting the System property rsiserver.property.file,
* as in the test ant target, or with java -Drsiserver.property.file=myNewPropertiesFile
*/
static String propLoc="/resources/rsi.properties";
static{
// First check system property to see if specific properties file is set
propLoc = System.getProperty("rsiserver.property.file", propLoc);
prop=new Properties();
InputStream is = Utils.class.getResourceAsStream(propLoc);
if(is==null){
log.debug("Failed to load Resource ["+propLoc+"] from Utils.class.getResourcesAsStream() trying classloader.");
ClassLoader cl=Utils.class.getClassLoader();
if(log.isDebugEnabled())
log.debug("ClassLoader = "+cl);
is=cl.getResourceAsStream(propLoc);
}

try {
//Throws IOException
prop.load(is);
} catch (Exception e) {
log.fatal("Exception loading Properties file.",e);
}
}




I'm at a loss to explain it, but I suspect (hope) that its some configuration problem.

No comments: