views:

794

answers:

9

For example:

MyApp is a web app that contains a properties file (server.properties) that describes config data (e.g. server names) for the app. In the development phase, server.properties is located in its own IDE project folder (a logical spot for it).

Now it's time to deploy MyApp. The IDE makes it quite trivial to jar up the class files as well as the supporting config files. Now we just drop the Jar in the appropriate web container and away we go....

A week later... the server config data that MyApp uses needs to change. Which makes more sense?

A. Modify the server.properties file back in IDE land and generate a completely new jar file. Redeploy. (which means bouncing the app for a simple configuration change).

B. Crack open the already deployed Jar and modify the server.properties file? (may have to call a refresh function in MyApp if server.properties is cached... but should not require a full app bounce. Also need to remember to modify source server.properties as well so future deploys don't revert server.properties to the old server names).

C. Make server.properties external to the jar file in the first place. Very similar to B's process, with the minor difference of keeping config data external to the jar (introduces different paths between development and production deploys)

D. Other:

Thanks!

+6  A: 

I'd go with D.

Try to load the properties files from outside the .jar then, if that fails, load the properties built into the jar.

This lets you push out a "ready made" configuration with each build (also reduces the complexity of a deployment, if by just one file), while also making overriding configurations possible and reasonably simple.

Kevin Montrose
+2  A: 

It depends. If the properties file contains data that is intended to be changed by the user of your application or library, than it should reside outside.

If it contains data that is static and you created the properties files just to avoid coding the values in the sourcecode or if the files are localized strings, I'd leave them in the jar. At least because a properties file invites people to change values ;)

Andreas_D
+1  A: 

Remember, that in J2EE, you are NOT guaranteed to be able to access files from outside the J2EE environment (no direct file access).

You would have to use JNDI to point to a datasource containing your data, or a properties file in your deployment artifacts.

Websphere, for example, doesn't allow direct file access by default.

Chris Kaminski
A: 

I've asked a similar question. We haven't figured it all out yet. But we're looking into URL Resources. Where the property-file is read directly from SVN. No need update anything other than the property file.

Tommy
A: 

Frequently it is a criteria that code should be migrated UNCHANGED from test to production. This implies that you may not edit embedded configuation files. Also you may end in a situation where you need to change a deployed configuration - which frequently is very cumbersome. Hence, we leave the configuraiton outside the jars.

For JEE applications consider JNDI or a property file in the classpath.

I have a web application where the configuration is retreived from a neighbor web application simply to separate the two. That turned out to be much easier.

Thorbjørn Ravn Andersen
+1  A: 

D.

Load the properties in the jar. Then create a new Properties using the jar-ed properties as the defaults. Then load from outside the jar. This allows select customization of properties.

KitsuneYMG
A: 

I use property files in webapps (WARs), but mostly for default values and stuff that's more or less immutable (since webapps shouldn't be updating their WARs even when they can).

For stuff like what you're talking about, however, I use JNDI. You can define the properties as resources in your web.xml file. That way, at worst, you update web.xml and not the app itself.

For some servers there are ways of overriding these resource values without touching the WAR at all. For example, in Tomcat.

I normally make one WAR for test, Q/A and production and override the environment-sensitive resources in exactly this was, using Tomcat's Context xml files. I consider this a lot better than having to build multiple WARs or to modify WARS, since the app I'm testing is almost identical to the app that's in production.

Tim H
A: 

I think the answer depends on whether you think you need to version control for the configs. (They could be production configs or configs for regression testing ...)

  • If you don't need version control, then option D with an external property file that overrides a property file is a good one. Options B and C are more open to stuff-ups, but if you really cared you'd be using version control :-)
  • If you need version control, option A gives you more control, but if you have the possibility of multiple deployments you may also want/need to version control the configs for each deployment. An example is separate deployments to test and production platforms.

Here's how we do this using Maven modules and Maven WAR file "overlays".

  1. We have multiple modules for the Java code components. These are JAR modules.
  2. We have "base webapp" module for the static content, JSPs and core configuration data (Spring wiring, default properties). This is a WAR module, so the result of building is a WAR that contains the above + all JAR files.
  3. Each distinct "site configuration" is a WAR module that contains site-specific overrides for properties, wiring files and content. The overriding is described using the Maven WAR "overlay" mechanism, and results in a new WAR being assembled from the "base" WAR and the overrides.

All of this is checked into version control, and you need to do a Maven build and WAR deployment to make configuration changes.

Stephen C
A: 

I develop J2EE applications using Spring. I was running around the same problem quite a long time and then found a solution. My problem was to specify the database properties in a properties file outside the war file that I deploy. The solution I found to this is to use the PropertyPlaceholderConfigurer and specify the location property to locate your system location as this,

This was quite simple and it worked just fine !