14

I'm writing a Java servlet that needs to read some site-specific configuration data; I would like it to be easily accessible/modifiable by the sysadmins at deployment time. There is no sensible default, so the data has to be provided by the site admin.
It consists of a few string key/value pairs (think Properties). It would only be read once (at initialization time).

I'm aware of this SO question and the ServletContext.getInitParameter() mechanism, but as far as my understanding goes, they require the data to be bundled in the servlet package (either as a properties file, or specified in the web.xml), which makes it inconvenient to upgrade the servlet code.

Is there any "standard" interface for a servlet to get this kind of key/value configuration data? It would be ok if the programming interface is the same everywhere, but the actual way of setting the configuration data depends on the actual servlet container being used.

I'm looking preferably at portable solutions, but I'd be content with something that only works in Tomcat and Jetty.

Community
  • 1
  • 1
Riccardo Murri
  • 1,045
  • 1
  • 11
  • 19
  • The recommended solution is to use JNDI as vanje answered below. Considering he also has double the upvotes as the 2nd best answer, please give him the credit he is due and mark his answer correct. – HipsterZipster Feb 17 '11 at 15:14
  • @Yoely: Done. The situation was not so clear-cut months ago when I posted the question... – Riccardo Murri Feb 21 '11 at 16:19

4 Answers4

18

The recommended way to configure an application server for a web application is per JNDI.

Every application server (including Jetty and Tomcat) allows you to configure JNDI parameters.

For Jetty you can add the following to your jetty.xml to add the JNDI parameter param.file:

<!--  JNDI java:comp/env --> 
<New id="param.file" class="org.mortbay.jetty.plus.naming.EnvEntry">
  <Arg>param.file</Arg> 
  <Arg type="java.lang.String"><SystemProperty name="jetty.home" default="."/>etc/config.properties</Arg> 
  <Arg type="boolean">true</Arg> 
</New> 

Then in your servlet you can read the JNDI parameter:

import javax.naming.InitialContext;
import javax.naming.NamingException;

...

public Object readJndi(String paramName) {
  Object jndiValue = null;
  try {
    final InitialContext ic = new InitialContext();
    jndiValue = ic.lookup("java:comp/env/" + paramName);
  } catch (NamingException e) {
    // handle exception
  }
  return jndiValue;
}


public String getConfigPath() {
  return (String) readJndi("param.file");
}

The way to set JNDI values differs for other application servers but the code to read the configuration is always the same.

vanje
  • 10,180
  • 2
  • 31
  • 47
4

The Servlet init parameters are the right (and standardized) way of defining properties which can be configured by the administrator. Many of the application servers provide a GUI backend where the parameters can be configured.

For an example for Tomcat, see Defining Tomcat servlet context parameters

Community
  • 1
  • 1
mhaller
  • 14,122
  • 1
  • 42
  • 61
  • +1 preferably via `context-param` (the JNDI route is good too, I think). – Bruno Sep 27 '10 at 14:46
  • 1
    In Jetty, servlet init parameters can be defined or overridden in the [override-web.xml file](http://docs.codehaus.org/display/JETTY/override+web.xml) – Riccardo Murri Oct 21 '10 at 08:11
3
  • Configure the external location of the properties - either via a jvm argument (when starting the servlet container), or in the web.xml

  • in the external location use config.properties and read it with java.util.Properties

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 1
    Or just add its path to the runtime classpath and load it from the classpath. – BalusC Sep 27 '10 at 14:41
  • 1
    Thanks: nice and simple. But, unless I misunderstand, this would require me to embed an absolute pathname into the web.xml, or the sysadmin to hack the JVM/servlet container startup script to define a property. Both solutions seem to have drawbacks... – Riccardo Murri Sep 29 '10 at 11:16
0

You may take Preferences or hack with user.home, user.dir, etc. But for a few key/value keep things simple.

Write a small Singleton to wrap around Properties and load them from a fix & absolute location

public class LocalConfig extends Properties {

  public static LocalConfig $ = new LocalConfig();

  private LocalConfig() throws IOException {
    load(new File("/etc/myconfig.properties"));
  }

}
PeterMmm
  • 24,152
  • 13
  • 73
  • 111