views:

49

answers:

3

Part of my webapp involves uploading image files. On the production server, the files will need to be written to /somepath_on_production_server/images. For local development, I want to write the files to /some_different_path/images.

What's the best way to handle these configuration differences?

One important requirement is this: I don't want to have to mess with the production server at all, I just want to be able to deploy a war file and have it work. So I don't want to use any technique which will require me to mess with the environment variables/classpath/etc. on the production machine. I'm fine with setting those on my local machine though.

I'm imaginine two possible general approaches:

  1. loading a special "dev" configuration file at runtime if certain conditions are met (environment variable/classpath/etc)
  2. flipping a switch during the build process (maven profiles maybe?)
+1  A: 

Have defaults in your WAR file corresponding to the production setting, but allow them to be overriden externally e.g. through system properties or JNDI.

String uploadLocation = System.getProperty("upload.location", "c:/dev");

(untested)

Thorbjørn Ravn Andersen
+2  A: 

Simple things like a String can be declared as environment entries in the web.xml and obtained via JNDI. Below, an example with an env-entry named "imagePath".

<env-entry> 
    <env-entry-name>imagePath</env-entry-name> 
    <env-entry-value>/somepath_on_production_server/images</env-entry-value> 
    <env-entry-type>java.lang.String</env-entry-type> 
</env-entry>

To access the properties from your Java code, do a JNDI lookup:

// Get a handle to the JNDI environment naming context
Context env = (Context)new InitialContext().lookup("java:comp/env");

// Get a single value
String imagePath = (String)env.lookup("imagePath");

This is typically done in an old fashioned ServiceLocator where you would cache the value for a given key.

Another option would be to use a properties files.


And the maven way to deal with multiple environments typically involves profiles and filtering (either of a properties file or even the web.xml).

Resources

Pascal Thivent
Thanks for the example code Pascal! I think this is what I'm looking for, and will get me where I need to be.
morgancodes
Is there any rule against putting WEB-INF inside <resources>? Seems a little hairy to me actually, since my jsps are all in there in a subdirectory. But that's where my web.xml is.
morgancodes
+1  A: 

Using a properties file isn't too difficult and is a little more readable the web.xml

InputStream ldapConfig = getClass().getResourceAsStream(
          "/ldap-jndi.properties");
      Properties env = new Properties();
      try {
        env.load(ldapConfig);
      } finally {
        if (ldapConfig != null) {
          ldapConfig.close();
        }
      }
jon077
Thanks jon. That, combined with maven profiles and filtering might work nicely, no?
morgancodes
Yes, it certainly would, but either are great.
jon077