views:

883

answers:

5

Hello, colleagues,
where do you store user-specific and machine-specific runtime configuration data for J2SE application?

(For example, C:\Users\USERNAME\AppData\Roaming\ on Windows and /home/username on Unix)

How do you get these locations in the filesystem in platform-independent way?

Thanks for your advice!

+1  A: 

You might want to look at Resource Bundles.

S.Lott
A: 

For user specific config, you could write a config file to the folder pointed to by the "user.home" system property. Would only work on that machine of course.

cagcowboy
+5  A: 

That depends on your kind of J2SE Application:

  • J2SE executable JAR file (very simple): use user.home System property to find home-dir. Then make a subdir accordingly (like e.g. PGP, SVN, ... do)
  • Java Web Start provides very nice included methods to safe properties. Always user-specific
  • Finally Eclipse RCP: There you have the notion of the workspace (also derived from user.home) for users and configuration (not totally sure how to access that tricky in Vista) for computer wide usage

All these approaches are, when used with care -- use correct separatorChar -- OS neutral.

BigD
+4  A: 

Java has a library specifically for doing this in java.util.prefs.Preferences.

Preferences userPrefs = Preferences.getUserNodeForPackage(MyClass.class); // Gets user preferences node for MyClass
Preferences systemPrefs = Preferences.getSysteNodeForPackage(MyClass.class); // Gets system preferences node for MyClass
Preferences userPrefsRoot = Preferences.getUserRoot(); // Gets user preferences root node
Preferences systemPrefsRoot = Preferences.getSystemRoot(); // Gets system preferences root node
R. Bemrose
+11  A: 

First on the format:

  1. Java property files are good for key/value pairs (also automatically handle the newline chars). A degree of structure is possible by using 'dot notation'. Drawback is that the structure does not allow you to easily enumerate top-level configuration entities and work in drill-down manner. Best used for a small set of often tweakable environment-specific settings
  2. XML files - quite often used for more complex configuration of various Java frameworks (notably J2EE and Spring). I would advice that you at least learn about Spring - it contains many ideas worth knowing even if you decide not to use it. If you decide to roll your own XML configuration, I'd recommend using XStream with customized serialization options or if you just need to parse some XML, take a look at XOM. BTW Spring also allows you to plug your custom XML configuration language, but it's a relatively complex task. XML configuration is best used for more complex 'internal' configuration that is not seen or tweaked by the end user.
  3. Serialized Java objects - a quick and easy way to persist the state of an object and restore it later. Useful if you write a configuration GUI and you don't care if the configuration is human readable. Beware of compatibility issues when you evolve classes.
  4. Preferences - introduced in Java 1.4, allow you to store typed text, numbers, byte arrays and other primitives in platform-specific storage. On Windows, that is the registry (you can choose between /Software/JavaSoft/Prefs under HKLM or HKCU). Under Unix the same API creates files under the user home or /etc. Each prefs hive can be exported and imported as XML file. You can specify custom implementation of the PreferencesFactory interface by setting the "java.util.prefs.PreferencesFactory" JVM property to your implementation class name.

In general using the prefs API can be a good or a bad thing based on your app scenario.

  1. If you plan to have multiple versions of the same code running on the same machine with different configuration, then using the Preferences API is a bad idea.
  2. If you plan using the application in a restricted environment (Windows domain or tightly managed Unix box) you need to make sure that you have proper access to the necessary registry keys/directories. This has caught me by surprise more than once.
  3. Beware from roaming profiles (replicated home dirs) they make up for some funny scenarios when more than one active machines are involved.
  4. Preferences are not as obvious as a configuration file under the application's directory. most of the desktop support staff doesn't expect and doesn't like them.

Regarding the file layout of the prefs it again depends on your application. A generic suggestion is:

  1. Package most of your XML files inside application's JAR either in the root or under /META-INF directory. These files will be read-only and are considered private for the application.
  2. Put the user modifiable configuration under *$APP_HOME/conf* . It should consist mainly of properties files and occasionally a simple XML file (XStream serialization). These files are tweaked as part of the installation process and are usually not user serviceable.
  3. Under the user-home, in a dot-directory (i.e. '~/.myapplication') store any user configuration. The user configuration may override the one in the application conf directory. Any changes made from within the application go here (see also next point).
  4. You can also use an *$APP_HOME/var* directory to store any other mutable data which is specific to this application instance (as opposed to the user). Another advantage of this approach is that you can move and backup the whole application and it's configuration by simple copy of one directory.

This illustrates some standard techniques for managing configuration. You can implement them using different libraries and tools, starting from raw JRE, adding Spring/Guice or going for a full J2EE container (possibly with embedded Spring)

Other approaches for managing configuration are:

  1. Using multiple base directories for running multiple instances of the application using different configurations.
  2. Using lightweight registries for centralized configuration management
  3. A centrally managed Configuration Management Database (CMDB) file, containing the host-specific values for each machine is rsync-ed every night to all production hosts. The application uses a templated configuration and selects from the CMDB during runtime based on the current hostname.
ddimitrov