Most Read This Week
Enabling Constant Substitution in Property Values
Enabling Constant Substitution in Property Values
By: Chris Mair
Dec. 1, 2001 12:00 AM
XProperties is a simple subclass of java.util.Properties that allows you to treat property values like constants, referring to and embedding them inside other property values. It handles the substitution of the constant value automatically and transparently when you call the getProperty() method.
Using constants in your property files can make them easier to read and maintain. This article describes an extension to the properties facility in Java that greatly enhances its functionality and usefulness. Like many other Java programmers I use the Properties class extensively for managing configuration information. In an application I recently developed, I had several properties (database URLs) in a configuration property file that shared the same value. I wanted a way to specify a constant in a property file rather than repeating the same value over and over.
My first approach was to add some extra logic where I read in the properties. I designated constant values by an arbitrary prefix ($). As I accessed a property value, I checked if it began with the prefix and, if so, performed the substitution with the named constant value.
I soon realized, however, that I could generalize this capability by moving the logic into a subclass of java.util.Properties. I could also greatly increase its usefulness by not limiting it to a simple, single substitution. Rather, I allowed a constant value to be embedded anywhere within the property value, even allowing multiple constants within the same value. I chose to indicate constant names by enclosing them in braces, abandoning the single prefix character. This makes the constant names obvious and unambiguous, as well as easier to parse.
The following properties illustrate the use of a constant within a property value:
SOURCE = SampleApp
The SOURCE property defines a constant value that's embedded within the value of the ErrorMessage property. As I mentioned earlier, to indicate that you wish to substitute the value of another property, surround its name with braces. Notice that the SOURCE property is defined just like any other property value. The only thing that makes it a "constant" is that it's referenced by another value. I've used all capital letters for the constant value, as is the convention in Java, but this is by no means a requirement. If the property name within the braces isn't found, then no substitution is performed and the property value is returned without modification.
You can substitute a constant anywhere in the property value, and even have more than one constant within a value, as in the following example:
CONST_1 = shoes and shipsIn this example, the "SomeValue" property evaluates to "shoes and ships and sealing wax."
Using constants within property values is especially useful when the same value occurs in multiple places, or when you build up a complex value from several reusable parts (e.g., file pathnames or URLs). Using constants also allows you to enumerate and assign descriptive names to potential property values. You may have to switch frequently between values for a property while developing a system, for instance, the URLs for unit test, system test, and production. One approach I've used is to include a property assignment for each possible value, but comment out the ones not being used. For example:
# MyURL = http://localhost:8080/abcWithout extra comments within the property file, however, it's unclear what each alternative represents. The extra commented lines also clutter the file, making it harder to read. Instead, by defining each alternative as a named constant, you can assign descriptive names to all the values, making the property files easier to understand, and also lessen the chance of making errors when switching between values. For instance, you can define:
In the above example, it's self-evident that the "MyURL" property is set to the value appropriate for the unit test environment. This example is included with several others in the sample property file shown in Listing 1. It illustrates some different ways to use constants within property values. Listing 2 contains Java source code to read in and access that property file using the XProperties class. Listing 3 shows the resulting output from running the code in Listing 2.
Note that the syntax for using the XProperties class - creating an XProperties object, loading the properties from a file, and accessing the property values - is exactly the same as for the java.util.Properties class. This demonstrates the power of inheritance. The XProperties class is designed to be a drop-in replacement for java.util.Properties. No changes or additions are made to the public API of the superclass. The XProperties class handles the constant substitution under the covers when you access a property value using the getProperty() method.
Another point to note is that you can nest the constant substitution to an arbitrary level. The XProperties class recursively evaluates each referenced constant. In Listing 1, the value of the property "MyHtmlFile" includes the value of the property "HTML_DIR". This, in turn, references the value of property "BASE_DIR", which then references "ROOT_DRIVE". You can see in Listing 3 that the value of "MyHtmlFile" evaluates to "c:/base/html/MyFile.html", incorporating all the constants used along the way.
Listing 4 contains the source code for the XProperties class. As you can see, it's not very complicated. The XProperties class overrides the getProperty(String) method. Handling the recursive substitution presented a minor challenge. How do you prevent an infinite recursive loop, as in the following example?
One option is to perform a complicated analysis to detect loops in the substitution tree. I chose a simpler approach. The XProperties class keeps track of the current depth of substitution (starts at zero and increments with each recursive substitution), and only allows up to an arbitrary (but easily changed) maximum depth - currently five. This logic is implemented in the private getProperty(String,int) method. This method performs the parsing and constant substitution, handles recursive invocation, if necessary, and checks the maximum substitution depth.
Like its superclass, the XProperties class includes a constructor that takes an existing properties object. These are default properties that are searched if a property key isn't found in the original property list. One use for this capability is to define a separate property file containing common constants that can then be accessed from multiple property files. All you need to do is load the property file containing the constants into a properties (or XProperties) object and then pass this object as the parameter to the XProperties constructor.
Be aware that the Properties.list(..) methods don't use the getProperty() method, and so don't perform any constant substitution before displaying property values.
Property files, like programs, can benefit from defining and using constants. You can specify a value once, and then reuse the same value for multiple properties, or you can have property values that are composed of several (potentially reusable) parts. These capabilities can be especially useful in configuration property files in which you need to specify complex values, like file pathnames or resource URLs. You can also enumerate and assign descriptive names to potential values when you need to frequently switch between alternative values for a property, for example, switching between test and production database URLs. The implementation of the XProperties class is fairly simple, but it provides a very useful extension to the properties facility in Java.
Reader Feedback: Page 1 of 1
Subscribe to the World's Most Powerful Newsletters
Today's Top Reads