I want to store configuration for a web project outside of the web project (ear/war file). The application shouldn't know in which container it's running (WebSphere/JBoss etc.).
What is the best way to handle this?
Is JNDI a clean way? If JNDI can solve my problems, how should I configure it? (Custom Objects?)
In my case are there only simple Key=>Value pairs (String,String) for SOAP/WS endpoints.
See this question for reading properties file outside of the WAR file.
See this question for reading variable values from JNDI. I believe that this is the best solution. You can read a String variable with this code:
The above code will work on all containers. In Tomcat you declare the following in conf/server.xml:
The above will create a global resource. It is also possible to define a resource in the context of application. In most containers the JNDI resources are available through a MBeans Management Console. Some of them offer a graphical interface to edit them. At most an application restart is needed, when a change is made.
How JNDI resources are defined and edited is container specific. It is the job of the configurator/administrator to apply the appropriate settings.
These are the benefits offered by JNDI:
you can just store then is a normal java properties file that is on the class path and just load the properties?
it is straightforward and pretty simple.. unless I am missing something
I use an environment variable to point to a URL (which probably is a file:// URL) that has my configuration in it. This is very simple to setup and doesn't require the JNDI infrastructure.
Here's some sample code (typed from memory - I haven't compiled/tested this):
My favorite places are : Environment Variables and Properties files (as suggested by Jared and kgiannakakis above.)
Database Table storing environment properties
However one other simpler solutions is to have Database table storing environment properties.
If your application uses database
We had a similar configuration requirement when deploying a webapp for different developers, and on Amazon's EC2: how do we separate configuration from the binary code? In my experience, JNDI is too complex, and varies too much between containers to be used. Also, hand-editing XML is very susceptible to syntax errors, so was the idea was thrown out. We resolved this with a design based on a few rules:
1) only simple name=value entries should be used
2) new configurations should be loadable by changing only one parameter
3) our WAR binary must be reconfigurable w/o repackaging it
4) sensitive parameters (passwords) will never be packaged in the binary
Using .properties files for all configuration, and using
System.getProperty("domain");
to load the appropriate properties files, we were able to meet the requirements. However, the system property does not point to a file URL, instead we created a concept we call "domain" to specify the configuration to use. The location of the configuration is always:$HOME/appName/config/$DOMAIN.properties
.So if I want to run my app using my own configuration, I start the app by setting the domain to my name:
-Ddomain=jason
on startup, and the app loads the file:
/home/jason/appName/config/jason.properties
This lets developers share configurations so we can recreate the same state of the app for testing and deployment without recompiling or repackaging. The domain value is then used to load .properties from a standard location, outside of the bundled WAR.
I can completely recreate the production environment on my workstation by using the production configuration like:
-Ddomain=ec2
which would load:/home/jason/appName/config/ec2.properties
This setup allows us to do have dev/QA/release cycles with exactly -one- set of compiled binaries, using different configurations in each environment. There's no risk of having passwords/etc bundled in the binaries, and people can share their configurations to recreate issues that we're seeing.