Java Development News:

Introducing JFig

By Bruce Conrad

01 Jan 2004 | TheServerSide.com

Introduction

Java applications are typically deployed in multiple environments and platforms, each requiring some unique configuration. Additionally, many applications consist of many component applications, all sharing common configuration data. JFig gives developers a simple yet powerful tool to manage their applications’ configuration. It allows them to:

  1. Store application configuration in one common repository of XML files
  2. Access configuration data using one common, convenient interface
  3. Easily define multiple configurations, dynamically modifying those variables that need to change in different situations
  4. Eliminate the error prone practice of defining the same configuration variables in multiple locations
  5. Ease the management, deployment, and control of configuration files

A Real World Scenario

On a recent project, I had a task to develop some code to send email messages to users every time a record with a status of “OPEN” had not been updated in 24 hours. This task would run as a thread every hour. In my case the record was a Work Permit, a review of steps that had to be taken before some work could be done. It could have been a problem log in a bug tracking system. Or an open order that hadn’t been shipped, a patient that needed a checkup. You get the picture.

BUT: I don’t want to send a message to the real user while I am developing, I want to send it to myself.

AND: When I am in test, I want the email to go to the QA people.

HOWEVER: The QA people want the task to kick off every 5 minutes so they can test it more easily.

FURTHERMORE: The other developers don’t want the damn thing to run at all on their machines.

AND WHAT’S MORE: The QA people want to be able to change the schedule interval and email address without having to bounce the server

AND JUST TO MAKE LIFE MORE COMPLICATED: The message subject line needs to say if it came from production, test, or development.

AND IF THAT WASN’T ENOUGH TO TURN MY CODE INTO SPAGHETTI: The message body needs an HREF to a URL. On production, I need a specific host name while on the other machines I can simply discover the host name.

AND I HAD TO BE READY: Just in case we need a training environment which has some mixture of these requirements.

I NEED PORTABILITY: So the .Net application can talk to the Web Services portion of my application on a different port for each environment to update the Work Permits.

AND FOR THE CLINCHER: I need to be able to maintain all of these configurations separately in CVS. I need to be able to tell what was what in each environment without logging into 16 different machines, even if the application is not currently running.

AND OF COURSE: It has to be done quickly.

AND, OH, BY THE WAY: One or more of these requirements might change tomorrow.

Current Alternatives to JFig

There are a number of reasonable approaches any reasonable developer might take to solve this problem. And there’s even more approaches that unreasonable developers might take (and that will undoubtedly be your boss, and that will end up being the approach you take).

  1. I could code 47 if statements for every possible permutation, hardcoding all the constants.. When QA reminds me that they want to change the email and the scheduling interval on the fly, I tell them they are out of luck

  2. Another, less cumbersome, approach is to make a property file for each combination. I call them all system.properties so only one can be stored in CVS. When a new property needs to be added for another part of my application, I need to remember to update all 16 files. But I can’t since everyone maintains their own copy on their own machine.

  3. I get clever and give each properties file their own name so now I am able to update all 16 when I need to.

  4. I make a series of .bat scripts for my Windows boxes, .sh for Unix, and .pl for masochists. I add four command line switches to each script for runtime flexibility. This brings my total of switches to 42 for other similar requirements. Every time I need to make a change to one of the scripts, I change each one. I make typos in only half, so half don’t run.

  5. I get really clever and decide to use ANT. I decide that I will make calls in ANT to invoke other build.xml’s for each environment. I find that the properties in ANT are immutable, once I’ve defined one I can’t change it. And I can’t partially define one property and build on it with another property from another build file. So I make a bunch of property files to start ANT, along with a bunch of scripts. Now I’m cooking. Except that the .NET weenies don’t want to use ANT to start their app and I don’t want to keep telling them what the port is for the Web Service every time I change it. And, still, I can’t change the email addresses or notify interval without restarting the application.

  6. I’m on the cutting edge so I use the new Preferences API in JDK 1.4. I can use XML files to define my configuration. In fact, I can use any data store to define my input. I can define different setups for different environments and use a tree structure with virtually unlimited depth. But the Preferences implementation does not come with a notion of extending or including configuration data. Nor do I have the ability to build or interpolate entries, overriding portions using previously defined entries or system properties. In short, I don’t have the ability to build my configuration dynamically.

Or, I get really smart and use JFig. Using JFig I know I can satisfy all the additional requirements starting at the first “BUT” and I’ll only need to write one or two lines of additional code. Really.

JFig is a configuration tool that allows me to use a hierarchy of XML files to dynamically define my application’s configuration depending on what environment I am running. I can put the 90% of my configuration variables that don’t change in a base project.base.xml file. For my test system, I extend project.base.xml, layering on the properties that are different for test in a separate file, project.test.xml . For production, I do the same. I extend project.base.xml, layering on the properties that are different in project.prod.xml .

This gives me tremendous flexibility and robustness.

  • When I add a value to the base configuration, it is automatically included in all the other configurations.
  • When I make my production release, I don’t need to make a bunch of untested changes at the last minute.
  • If I need to override a particular value, I can
  • I can store all my configuration files in my source repository
  • I can change the configuration on a running system
  • I don’t need to maintain multiple copies of property files.
  • I don’t need to maintain multiple scripts with lots of command line switches

I can make my hierarchy as deep as I want, even with multiple inheritance. For example, I can set up a default development environment, then tweak that even further to configure personalized environments for each developer. To do that, I once again extend project.base.xml, layering on the unique differences for development in project.development.xml . For my personalized configuration I extend project.development.xml. Then, I can add the couple of entries that I need for my own personal development environment in a project.myDevelopment.xml .

Setting up JFig Configuration Files

Getting back to the original specifications, I start with my project.base.xml. In this file, I define the default value of my entries, separating entries into logical sections. I use two rules of thumb to define the default values; what is safest and what requires the fewest changes and (theoretically) the fewest bugs in the extending files. I don’t want to have developers connecting to the production instance on the database because someone accidentally deleted or misspelled the database entry in the project.development.xml.

In this case, I define the notifyFrom and notifySubject entries utilizing variable substitution. In subsequent configurations if I change the “instance” entry in “myproject” section, I change both notifyFrom and notifySubject. By isolating my changes, I can reduce the number of overrides I need in the extending configuration files.

PROJECT.BASE.XML
<configuration>
    <section name="myproject">
        <entry key="instance" value="base" />
        <entry key="isProduction" value="false" />
        <entry key="httpHost" value="xyz" />
    </section>

    <section name="webServices">
        <entry key="port" value="81" />
    </section>

    <section name="workPermit">
        <entry key="notifyInterval" value="60" />
        <entry key="updateInterval" value="24" />
        <entry key="isNotifyOn" value="false" />

        <entry key="defaultNotifyAddress" value="qaGuy@xyz.com" />

        <entry key="notifyFrom" value="[myProject]{instance}@xyz.com" />

        <entry key="notifySubject" value="[myProject]{instance} - Work Permit has not been updated in [workPermit]{updateInterval} hours"
    </section>
</configuration>

In project.test.xml, I include or extend project.base.xml. This gives me all the entries defined in that file. I override those values that are unique to the test environment. In the workPermit section, I set isNotifyOn to true, the notifyInterval to 15.

PROJECT.TEST.XML
<configuration>
    <include name="project.base.xml"/>

    <section name="myproject">
        <entry key="instance" value="Test" />
    </section>

    <section name="workPermit">
        <entry key="notifyInterval" value="15" />
        <entry key="isNotifyOn" value="true" />
   </section>

</configuration>

Now we set up the production configuration. Like project.test.xml, I Include the base configuration. Then, I explicitly set an entry, isProduction, for parts of my code that check if we are in production. I could use some String matching to check the instance entry (instance=Production), but I’d rather not take that chance. In this case, I use isProduction to decide if I send the notification to a default email id or to the owner of the Work Permit. And, of course, I set isNotifyOn to true.
PROJECT.PROD.XML
<configuration>
    <include name="project.base.xml"/>

    <section name="myproject">
        <entry key="instance" value="Production" />
        <entry key="isProduction" value="true" />
    </section>

    <section name="workPermit">
        <entry key="isNotifyOn" value="true" />
    </section>

</configuration>

We’ll define a few more configuration files in just a bit. But before you fall asleep reading XML files, we’ll jump into the API.

Using the JFig API

Now that we’ve created a couple of JFig files, how do we get information from them. There are a number of other methods to access JFig configuration. Before using them, however, I would recommend calling:

JFig.initialize();
or
JFig.initialize(JFigLocator);

passing in your own, personalized, JFigLocator (more on that in a minute).

After JFig has been initialized, I can get data from it with a simple call to:

JFig.getInstance().getValue(sectionName, key);

JFig uses the Singleton pattern, there’s only one of them. If the JFig Singleton has not been initialized, it will lazily process the config files into an instance of JFig object on the first call. The advantage of explicitly calling the initialize method is it will throw a JFigException if any of the JFig processing goes awry, where the lazy initialization does not.

Let’s back up a bit. How does JFig know what files to process? By default, it will look for a file called <hostname>.config.xml in the classpath. This is convenient in development, but I would recommend that users explicitly specify their configuration file, especially on their production system. This is done by passing the command line switch, for instance:

java –Dconfig.filename=prod.project.xml <yourClassName>

I know, I know. Here I’ve trashed other schemes that force you to maintain scripts and the use of properties to configure applications. The difference here is you are cleanly separating all of your configurations into your JFig files, then using one property to call the appropriate configuration which is built dynamically, much like a Factory pattern. And any time you quote from the Gang of Four, you can get away with most anything.

The JFigLocator also allows you to tell JFig to look for files not in the classpath. In addition, JFig provides a means to define your own JFigLocator and develop your own scheme for looking for config files. You could have it look in the classpath, then in a WEB-INF directory or any crazy scheme you need to support.

Another helpful method after initialize is:

JFig.print();

This will tell you how all of your overrides and variable substitution worked out. This is a nice thing to have in your log should questions arise later. There are also jsp pages available to display configuration information on a running system. This can be quite helpful when someone asks what is the Work Permit notification interval and you don’t want to wade through three or four levels of configuration files to figure it out. A call to print() after initializing test.config.xml yields the following results:

INFO JFigDictionary.print - --------------------------------------
INFO JFigDictionary.print -
INFO JFigDictionary.print - Section: myproject
INFO JFigDictionary.print - Key: httpHost Value: xyz
INFO JFigDictionary.print - Key: instance Value: Test
INFO JFigDictionary.print - Key: isProduction Value: false
INFO JFigDictionary.print -
INFO JFigDictionary.print - Section: webServices
INFO JFigDictionary.print - Key: port Value: 81
INFO JFigDictionary.print -
INFO JFigDictionary.print - Section: workPermit
INFO JFigDictionary.print - Key: defaultNotifyAddress Value: qaGuy@xyz.com
INFO JFigDictionary.print - Key: isNotifyOn Value: true
INFO JFigDictionary.print - Key: notifyFrom Value: qaGuy@xyz.com
INFO JFigDictionary.print - Key: notifyInterval Value: 5
INFO JFigDictionary.print - Key: notifySubject Value: Test – Work Permit has not been updated in 23 hours
INFO JFigDictionary.print - Key: updateInterval Value: 24
INFO JFigDictionary.print - --------------------------------------

Other JFig methods for accessing JFig values are:

JFig.getInstance().getValue(sectionName, key, defaultValue);
JFig.getInstance().getBooleanValue(sectionName, key, defaultValue);
JFig.getInstance().getIntegerValue(sectionName, key, defaultValue);
JFig.getInstance().getFloatValue(sectionName, key, defaultValue);
JFig.getInstance().getValuesStartingWit(sectionName, key);
JFig.getInstance().getArrayValue(sectionName, key);


There are a few more helpful methods in the API. One is
JFig.getInstance().reprocessConfiguration();

reprocessConfiguration() allows you to edit the configuration file on a running system, then signal JFig to reprocess its files. It’s pretty easy to set up a GUI or some other mechanism to have your running system make this call. JFig allows you to implement a JFigListener that will enable a class to be notified when JFig values change. In most cases, it is fine to call JFig each time a value is needed and no Listener is required to use the reprocessed JFig instance. In other cases, one might call JFig once to initialize a File object. If you want to have your class reinitialize the File object when JFig values have changed, simply implement JFigListener.

JFig provides several techniques for setting system properties. A JFig method, setSectionAsProperties(sectionName), allows the user to convert any JFig section to system properties or another Properties object.

Another technique is to define a special section in the JFig configuration file named “properties”. Any key in this section will be set as a system property.

Back to our Requirements

Now that we’ve seen how to set up our configuration files and had a look at the API to access the information in them, the implementation of our complex notification requirements becomes relatively simple.

On my development machine, I might have my initial JFig file in my classpath and set to my host name. Then I don’t need anything at all in my java command, as JFig will find it automagically. On production, I have named my initial JFig file test.project.xml. In that case, I tell my application about it with a property switch:

java –Dconfig.filename=test.project.xml <yourClassName>

In my application’s initialization class I make an explicit call to initialize JFig. I could let it initialize lazily, but I prefer to call initialize because it will throw an exception if there are any problems. Immediately after initialization, I print the results:

try {
 JFig.initialize();
 JFig.getInstance().print();
} catch (JFigException e) {
 logger.error("JFig failed to initialize "+e.getMessage(), e);
}

Also in my application’s initialization class I call JFig to find out if we want to start the notification thread at all. (One thing to note in this and the other code samples is that I am passing default values in the third parameter. If I didn’t I would need to catch and handle JFigException. This is a matter of choice based on your requirements.):

if  (JFig.getInstance().getBooleanValue("workPermit", "isNotifyOn", "false") {
 startNotificationThread();
}

At the point in my Thread where I want to sleep for a given amount of time, I call JFig instead of using a hardcoded value:

int sleepTime = JFig.getInstance().getIntegerValue("workPermit", "notifyInterval", "60") * 10000;

When I want to determine if I want to send the notification to a real user or to my test user I add:

if  (JFig.getInstance().getBooleanValue("myProject", "isProduction", "false") {
 emailAddress = workPermit.getUser().getEmailAddress();
} else {
emailAddress = JFig.getInstance().getValue("workPermit",  "defaultNotifyAddress", "nobody@xyz.com");
}

My message subject line and “from address” are also easily accessible:

subjectLine = JFig.getInstance().getValue("workPermit",  "notifySubject", "");
emailFrom = JFig.getInstance().getValue("workPermit",  "notifyFrom", "");

As I mentioned earlier, JFig can use variable substitution to reduce the number of entries in the configuration file. This is done with variables defined in this or included configuration files. It can also be done with system properties. In this example, I modify the notifySubject and the notifyFrom entries so they are built dynamically. This eliminates the need to define them in included files

I can even modify my query for how old my records should be. This wasn’t in the requirements, but I prefer to externalize my constants instead of using hardcoded values.

updateInterval = JFig.getInstance().getValue("workPermit", "updateInterval", "24")

If my testers want to change the notification interval or the default email address on the running system, they can modify test.project.xml. Then I would have to provide a mechanism (ie JSP, WebServices) to have my application call:

JFig.getInstance().reprocessConfiguration();

The changes will persist if the app is restarted, but will be lost if the app is redeployed or rebuilt.

The final result shows that I’ve satisfied all my requirements with virtually no additional code than if the requirements had not existed. In fact, since I had an easy way to externalize my constants, I would argue that the code is even more robust than if I hadn’t used JFig. I’ve added tremendous flexibility at no additional expense. Sure, I had to set up my JFig files, but I recoup that cost the second time I use JFig in another part of my application.

Further on Down the Road

We’ve seen how to set up a few configurations and how to use the JFig API. But the real power of JFig comes with leveraging existing configuration data. These sample files are kept simple for the sake of making the examples easier to understand. But a real JFig configuration might define file paths, database connections, datasources, and many other configurable values.

Now we go a bit further in depth using JFig to set up a generic development and a personalized development environment. First a quick reprint of project.base.xml for easy reference.

PROJECT.BASE.XML
<configuration>
    <section name="myproject">
        <entry key="instance" value="base" />
        <entry key="isProduction" value="false" />
        <entry key="httpHost" value="xyz" />
    </section>

    <section name="webServices">
        <entry key="port" value="81" />
    </section>

    <section name="workPermit">
        <entry key="notifyInterval" value="60" />
        <entry key="updateInterval" value="24" />
        <entry key="isNotifyOn" value="false" />

        <entry key="defaultNotifyAddress"
value="qaGuy@xyz.com" />

        <entry key="notifyFrom"
value="[myProject]{instance}@xyz.com" />

        <entry key="notifySubject" value="[myProject]{instance} - Work Permit has not been updated in [workPermit]{updateInterval} hours"
    </section>
</configuration>

We’ll define the generic development environment in project.development.xml.Like test, it also includes project.base.xml. Most of the values defined in project.base.xml are “safe” and match the development environment so project.development.xml doesn’t need much.

One thing to note is that by changing the “instance” entry in section “myproject” we change both notifyFrom and notifySubject since they contain a reference to [myProject]{instance}. By isolating common differences, you can reduce the number of changes in extending files. Another point of interest is that even though “myproject” and “myProject” don’t match, the substitution will still work. One of the friendlier things about JFig is that it is case insensitive on all “section” and “key” strings. (Case sensitivity is a pet peeve of mine).

PROJECT.DEVELOPMENT.XML
<configuration>
    <include name="project.base.xml"/>

    <section name="myproject">
        <entry key="instance" value="development" />
    </section>
</configuration>

Now I’m the guy who’s developing this Work Permit Notification so I need my own personalized development configuration. I was a nice guy and turned the notification off on my fellow developers machines (isNotifyOn=false), but I need it on for myself. And I want the notifyInterval even quicker, down to 5. Also I want the emails to go to me.

I’ve also defined the updateInterval as a property value. I use updateInterval in my SQL query to select how long it’s been since a record has been updated. While I’m developing, maybe I want flexibility to change this on each run. So now I can set this value from the command line as a standard java switch using
java –Dworkpermit.updateInterval=24 <className>

One more thing. I name my file schmoopsie.config.xml. That’s because “schmoopsie” is my host name (don’t ask). The default JFigLocator will look for a file named <hostname>.config.xml. I find it convenient to use this default in the development environment but prefer to force an explicit file name in other environments. For one thing, using the default limits you to one JFig configuration per host. For another, it ties the application to a particular host.

SCHMOOPSIE.CONFIG..XML
<configuration>
    <include name="project.development.xml"/>

    <section name="myproject">
        <entry key="instance" value="MyDevelopment" />
    </section>

    <section name="workPermit">
        <entry key="notifyInterval" value="5" />
        <entry key="isNotifyOn" value="true" />
        <entry key="updateInterval" value="$workpermit.updateInterval$" />
    </section>

</configuration>

Other developers are also free to set up their own personalized environments. They may want to define different directory paths that reflect the setup of their own machines. Or they may have individual settings that they want to change as they work on other parts of the application.

Other Uses of JFig

When a man has two watches, he never knows what time it is. When a man has two configuration repositories, all hell breaks loose. Most of the preceding example concerned the flexibility offered by JFig to configure an application in multiple environments. But using JFig has many other advantages.

In many n-tier applications, multiple applications need to work together within the same environment (Production, Test, Development). The JNDI address may be defined on your app server, but often times a client such as IPlanet is running in its own JVM and needs to talk to the app server. Perhaps you have Webmethods also talking to the app server. When somebody changes the JNDI name on one, they need to coordinate a change in all three places. Furthermore, Webmethods may be writing files to the same directory that your app server needs to read from, or vice versa. If the application server and Webmethods get out of synch on the directory name, the whole application can stop working. Sometimes these problems are obvious and easy to fix, sometimes they are not even spotted until damage has been done. Wouldn’t a common repository solve some of these problems?

Many applications that run on a server or desktop come with configuration files. Generally, the prescribed method to configure the application is to manually edit or otherwise update these files. Local modifications are mixed in with the “factory” defaults. When you get another copy of the application, you must often repeat the time consuming task of re-applying these modifications (think Apache Web Server). Wouldn’t it be more sensible to layer local modifications on top of a base configuration, thereby making it apparent what has changed and easier to re-implement?

Sometimes a new developer comes on and it takes way too long to configure a development environment to start doing useful work. They need to set up environment variables on their machine, modify property files and startup scripts. Finding the one thing that is hanging them up can often be very time consuming. Wouldn’t a better abstraction of configuration parameters ameliorate this situation?

Most of us know that it is good practice to externalize constants from our code, yet we don’t do it. That’s because we don’t have a good scheme to store these constants, nor do we have a friendly API to retrieve them. A better API than the current getProperty method might make developers more likely to use it.

Often, we need to set up a new test environment where everything is the same as another environment except for a few things. You copy another test environment and make a few tweaks to some scripts for the changes. It all works…for a while. You try to use it in a couple of months but first you need to migrate a bunch of things that changed on your application in the interim. A day later, after correcting a subtle typo, you have it working.

Even worse, you become afraid to make changes to your application because you know it will require propagating those changes to multiple environments and the person that used to know all the ins and outs of that are gone. Your application becomes brittle.

Using JFIG solves many of these problems. A common repository allows multiple components to change in synch. Abstracting and externalizing configuration settings minimizes the differences on individual deployments. A robust API makes it easier to access configuration data. Often, just having a convenient place to put something makes you more likely to put things there.

Using JFig with other Applications

In a perfect world, there would be no hunger, Jennifer Lopez would be serving cocktails at the Peppermill Lounge (while Ben buses tables), and all applications would use JFig. If all applications used JFig, it would allow us to combine all our configurations into one common repository and eliminate the need to define the same variables over and over. While these are all lofty goals, let’s concentrate on the last one. Because, while there’s not much we can do about J Lo, there are ways of using JFig to configure many other applications.

Applications like Weblogic allow users to pass properties at startup. A two line java program that calls JFig, followed by a call to Weblogic eliminates the need to manage Weblogic startup properties in startup scripts, property files or otherwise. It would be practical to leave the rest of the Weblogic configuration that never changes and is used only by Weblogic in the Weblogic configuration files. Those values that are shared and/or benefit from dynamic configuration are best managed by JFig.

Maven is another example of an app that would benefit from JFig configuration management. Maven is a great tool and even has some ability to “subclass” configuration files. However, its scheme of various property files all with the same name but in different explicit locations (home directory, maven directory and one or two other places) is not one of its strong points. Plus, it’s just one more place to replicate many of the variables that are defined in other places in your application. The java class, MavenFig, is provide with the JFig distribution. It is simply the two lines mentioned above, a call to JFig followed by a call to Maven.

AntFig, also provided in the JFig distribution, is similar to MavenFig and enables you to consolidate your configuration variables under one umbrella. While Ant has some of the features of JFig (property and variable substitution) Ant lacks the hierarchical capabilities of JFig. Ant allows you to include other files but properties are immutable. The first one wins instead of the last.

Log4J fits in very nicely with JFig. It allows property value substitution within its configuration files much the same as JFig. So a call to JFig might set properties to define different log levels for your production, development, or test environments or different directories to store log files. A subsequent call to Log4J configure() methods and you have JFig’ed Log4J.

Applications that don’t provide a properties interface are not as easily configured by JFig. If you are truly looking for centralized configuration nirvana, you can get closer. It may be possible to obtain a handle to their configuration object and make calls to set those properties that are best managed by JFig (those that you want to manage centrally and/or dynamically).

Still another alternative is using a call to JFig’s convert(inFile, outFile) method. The call to convert allows you to define a given configuration file in a template using JFig substitution syntax (see sections SUBSTITUTION VARIABLES and PROPERTY VARIABLES). If, for example, you want to use https in production but http in development, you can define a JFig-like variable (ie [struts]{httpProtocol} ) in a struts-config.template. A call to convert(a struts-config.template, a struts-config.xml) prior to struts initialization will achieve the desired results.

(Caveat Emptor: JFig convert is a new feature beginning with version 1.4 and has not been used in any application at this point).

Preferences API Redux

The new Preferences API, just released in Java 1.4, recognizes and addresses many of the shortcomings of Properties files. Its goal is to give developers the ability to use “preference and configuration data to adapt to the needs of different users and environments.” In many respects, the API is very similar to JFig’s various getValue methods. It also provides for a more flexible XML hierarchy than JFig. However, the current Preferences implementation does not have JFig’s functionality to “extend” or include configuration files. Nor does it have the ability to override or substitute values with data from other entries or system properties. These are the two main features that give JFig the ability to reuse and dynamically construct configuration for a given environment. Still, Preferences provides some great new functionality and it is quite possible that a future implementation of JFig may extend or adapt it to provide the best of both worlds.

Conclusion

The lack of a coherent configuration scheme in Java has a couple of other not so obvious downsides. All of the careful testing you’ve done when adding new configuration parameters in development and test gets thrown away when you go to production. One strategic typo, and weeks of testing are for naught. It would be much better if you had some assurance that your tested configuration changes would make it effortlessly and correctly to production.

Another is that developers are less prone to use configuration to its full potential. You might never think to configure selected values on test differently than production because it’s too much trouble. Or you might end up with a number of hardcoded constants in your code that would be much better to be externalized.

JFig provides a way to dynamically configure your Java application to run in many different environments. It enables you to define a central configuration repository that can be used by more than one application, especially those that need to use the same configuration data to work together. It promotes the reuse of configuration data which reduces errors. Best of all, once you start using JFig, you may start to think of ways to add features to your application that would be unthinkable without it.

Links

To visit the JFig home page and read more: http://jfig.sourceforge.net/
To download JFig, go to: https://sourceforge.net/project/showfiles.php?group_id=85731&release_id=197661
For a complete set of JavaDocs (also included with the complete download):
http://jfig.sourceforge.net/javadocs
For more on Preferences:
http://java.sun.com/j2se/1.4.2/docs/guide/lang/preferences.html
http://java.sun.com/developer/Books/javaprogramming/jdk14/javapch10.PDF