Today's applications are deployed in a variety of environments, and one of the ways to manage the complexity is by providing configurable components where the users and system administrators can modify application settings for their specific environments. A variety of options are available to developers for managing application configurations and preferences. They range from platform-specific solutions like the Windows registry to network-enabled configuration information via JNDI. In the Java world, most applications rely on the java.util.Properties API; however, the location and naming conventions used within properties files are not standardized.
JDK 1.4 introduces the Preferences API. This API has a goal of providing a consistent framework for the management of preferences and configuration data for Java applications. Acknowledging that a number of solutions exist across various operating systems, the API stays away from any specific implementations. While the default implementation supports persistence in XML format, a variety of other storage/retrieval mechanisms could be supported.
The API is based on a simple node hierarchy. There are two separate tree structures. One deals with user preferences and the other is for system preferences. It is up to the application developer to decide which features are user preferences and which are system preferences. For example, configurations such as colors and desktop layout are typically considered user preferences while installation parameters are considered system preferences.
|Overall, the Preferences API is a step in the right direction.|
The main class in the java.util.prefs.Preferences package is Preferences. The easiest way to manage the various nodes is to follow the hierarchical model of Java packages. Suppose we have a package called com.foo.myApp. To access the user preferences for that package we could use the following:
Preferences prefs = Preferences.userRoot().node("/com/foo/myApp");
To get the system preferences, we would use:
Preferences prefs = Preferences.systemRoot().node("/com/foo/myApp");
If we are dealing with instances of a class, we could simplify the above, because the package name associated with an instance is known. We could simply write:
Preferences prefs = Preferences.userNodeForPackage(this);
this refers to the current instance. For system preferences, we call the
systemNodeForPackage() method instead.
Once you have obtained an instance of the Preferences class, you can set or get specific preferences. You have a variety of "put" methods such as
putLong(), etc. They all take a key and a value. The key is always a String and the value depends on the specific "put" method. For string values, simply use
put(String key, String value) .
To read preferences values, you use the various "get" methods available like
getLong(), or just
get(). One interesting requirement of the API is that all "get" methods must provide a default value in case no value has been set for a particular preference or when the storage system is not available. The application can be designed to run with default values or to stop pending availability of the storage system. The choice is left up to the application designer.
One method I found useful is
exportSubtree(). It generates an XML document showing all the preferences. It takes an OutputStream as its argument, so you can just pass to it an instance of FileOutputStream to output the XML result into a file.
Overall, the Preferences API is a step in the right direction. Without favoring a particular implementation, it provides a framework for managing, reading, and writing application configuration and preference information. Since the API is included in the JDK 1.4 distribution, you can start using it in your applications right away.