Use a mechanism to classify configuration parameters Configuration parameters are the values that allow you to configure the behavior of your applications without changing any code. These values control how parts of the application look or act. String messages, IP addresses, user interface layout measures, and the maximum number of objects in cache memory are sample configuration parameters commonly found in software applications.Property files and XML document files are often used to organize application configuration parameters. Usually these configuration files are read by an application when it first starts up. A property file contains a set of strings, where properties are stated with the syntax name=value. On the other hand, XML document files, when used as configuration files, provide configuration parameters in an XML element <name>value</name> syntax. The following are sample configuration parameters displayed as a property file and as an XML configuration file.Sample author.properties configuration file name.first=paulo name.last=caroli url=www.caroli.org Sample author.xml configuration file <?xml version="1.0" encoding="ISO-8859-1" ?> <author> <name> <first>paulo</first> <last>caroli</last> </name> <url>www.caroli.org</url> </author> In simplistic application development, configuration parameters and configuration files are not explicitly delineated. In such applications, configuration values are embedded in the application’s code; these are usually called hard-coded values. Applications containing hard-coded values are difficult to alter. To simply change a hard-coded value, the application’s code must be altered, recompiled, and redeployed. Also, hard-coded values require a developer’s expertise. While property files can be easily altered by nondevelopers, hard-coded value changes require a developer to locate and implement the configuration value changes.Using configuration files is highly recommended, but managing configuration parameters grows more complicated for applications that execute in several environments. Common in software organizations, some applications execute in distinct runtime environments according to the company’s development phases. In my company, during an application release lifecycle, the application executes in development, integration, quality assurance, staging, and production environments. Each environment requires different configuration files and values. For example, the maximum number of objects in cache memory might be 10,000 in a production environment, while, in a development environment, a much lower value is used during alpha tests. This article introduces a configuration mechanism, a uniform solution for dealing with all of a Java application’s configuration parameters regardless of environments. The proposed configuration mechanism is composed of three interconnecting parts: configuration folder schema, configuration parameter reader, and launch command outline. The figure below illustrates each of the mechanism’s parts. The following sections address each part.Configuration folder schemaThe proposed configuration folder schema is the structural backbone of the configuration mechanism. Java applications are typically deployed in multiple environments and platforms, each requiring some unique configuration. Runtime environments inevitably need conflicting settings, and the settings might significantly differ according to an environment’s specific needs. Examples of environment-specific configuration values are: IP addresses, database connectivity, or application timing and boundaries values.The following is a generic application’s configuration folder schema: configuration/ common app configuration files... env1/ env1 specific configuration files... env2/ env2 specific configuration files... ... envN/ envN specific configuration files... In this article’s proposed configuration folder structure, the common environment’s configuration files are located under the configuration/ folder, whereas the environment-specific configuration files are placed under the environment_name/ folder. Each environment available for the application must have a respective environment_name folder.The configuration folder should be specific for each application. I recommend adding the configuration folder to the application folder structure as follows: app/ classes/ configuration/ lib/ src/ Using one configuration folder per application is preferred over having a common configuration folder for several applications so you can individually configure the applications without affecting the others. Configuration parameter readerApplications consist of many components, all sharing common configuration data. This section introduces ConfigurationReader and Commons Configuration from the Apache Jakarta Project, a combination of approaches that gives developers a simple yet powerful tool for accessing their applications’ configuration data.A crucial part of the configuration mechanism is reading the configuration values. Instead of developing a new component for reading configuration files, I based the ConfigurationReader implementation on an already established configuration-reading library, the Apache Jakarta Project’s Commons Configuration library.Commons Configuration library The Commons Configuration library provides a generic configuration interface that enables an application to read configuration data from a variety of sources. This library was used in the Turbine and Velocity projects (also from the Apache Jakarta Project) before being introduced in the Jakarta Commons project. Visit the Commons Configuration Website for more details on this great library.In a nutshell, the Commons Configuration library provides a Configuration component to use for accessing the configuration values. The Configuration component is obtained by a configuration factory that initializes the configuration values according to the configuration datasources indicated in a configuration definition file—config.xml. The following is the sample configuration definition file provided from the Commons Configuration Website:Sample config.xml file <?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="usergui.properties"/> <xml fileName="gui.xml"/> <xml fileName="tables.xml"/> </configuration> ConfigurationReader component The ConfigurationReader component encapsulates the access to the environment-specific configuration parameters. Based in the configuration mechanism folder structure and the Commons Configuration library, ConfigurationReader retrieves the Configuration interface by setting the ConfigurationFactory with the proper environment-specific config.xml file.To enable the proper ConfigurationReader component functioning, a config.xml file must be added in the proposed configuration folder schema for each environment. Below is the previously presented configuration folder schema, with the added environment-specific config.xml files: app/configuration/ common app configuration files... env1/ config.xml env1 specific configuration files... env2/ config.xml env2 specific configuration files... ... envN/ config.xml envN specific configuration files... The code below shows how the ConfigurationReader component retrieves the proper Configuration component according to the env system property defined as the JVM system parameter:ConfigurationReader.java import org.apache.commons.configuration.*; // The following libraries are required for Apache Commons-Configuration usage: // commons-configuration, commons-beanutils, commons-collections, // commons-digester, commons-lang, commons-logging, xerces and dom4j public class ConfigurationReader { Configuration config = null; public ConfigurationReader() {} public void load() throws ConfigurationReaderException { try { ConfigurationFactory factory = new ConfigurationFactory(); factory.setConfigurationFileName(this.getEnvConfigXMLPath()); config = factory.getConfiguration(); } catch (Exception exc) { throw new ConfigurationReaderException(exc.getMessage()); } } public Configuration getConfiguration() throws ConfigurationReaderException { if (config == null) { load(); } return config; } private String getEnvConfigXMLPath() { StringBuffer srtBuffer = new StringBuffer("configuration/"); // System env variable is mapped to configuration/[env] folder srtBuffer.append(System.getProperty("env")); srtBuffer.append("/config.xml"); return srtBuffer.toString(); } } Note that the system env property is read at runtime; which lets the same application code execute independently of the environment and maintain the proper configuration files’ usage. Launch command outlineAutomatic recognition of the runtime environment allows your application to benefit from the proposed configuration folder schema. Such recognition allows the proper reading of the environment-specific configuration according to the specific environment_name/ folder.You initiate the Java runtime environment by using the java command, which launches a Java application by starting a Java runtime environment, launching specified options, and loading the specified program. The syntax for starting a Java application is: java [options] -jar file.jar [arguments] java [options] class [arguments] The following arguments are used in the java command: options: Command line options (optional)file.jar: The name of the jar file to invokeclass: The name of the class to invokearguments: The arguments passed to the main function (optional)The code below shows the launch command outline for starting an app.jar application in the env1 environment. The launch command outline marks the JVM with its environment name during the launch process. The -D<property_name>=<value> is a standard option supported by the launcher for setting a system property. java -Denv=env1 -jar app.jar At application startup, the -Denv=env1 option sets the env system property with the env1 value. Further, your application’s launch command must contain the -D env=environment_name option, where environment_name is the environment in which the application executes. Please note that environment_name in the launch command must match environment_name used in the configuration folder structure.A Hello World sample applicationThe HelloConfig sample application illustrates each part of the proposed configuration mechanism. HelloConfig basically reads and displays the following properties: Application Hello stringApplication World stringAuthor first name stringAuthor last name stringAuthor URL stringRuntime environment greetings stringRuntime environment goodbye stringThese configuration values are organized as follows: hello.properties and author.xml are configuration files common for all runtime environments, whereas env.properties are configuration files specific to the runtime environment. For the scope of the HelloConfig application, development, staging, and production are the available runtime environments. Below are the sample configuration files’ contents.hello.properties # environment common properties sample.hello=hello config-mechanism sample.world=world author.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <author> <name> <first>paulo</first> <last>caroli</last> </name> <url>www.caroli.org</url> </author> development env.properties # environment specific propertiesenv.greetings=yeap app working in the development environment!!! env.goodbye=adios from the development environment; later dude staging env.properties # environment specific properties env.greetings=all looks good in staging. env.goodbye=staging environment end of execution. bye for now. production env.properties # environment specific properties env.greetings=proper execution in production system. env.goodbye=finalizing hello config system. The following sections explain the steps involved in organizing the configuration files, reading the configuration data, and packaging and launching the HelloConfig application. This sample’s development is entirely based on the configuration mechanism proposed in this article. helloconfig.jar is available for download from Resources.HelloConfig configuration folder schemaThe HelloConfig application’s configuration folder schema: helloconfig/configuration/ author.xml hello.properties development/ config.xml env.properties staging/ config.xml env.properties production/ config.xml env.properties In the HelloConfig configuration folder structure, the common environment’s configuration files hello.properties and author.xml are located under the configuration/ folder, but config.xml and env.properties, which are environment-specific files, are accordingly placed under the configuration/development, configuration/staging, and configuration/production folders.HelloConfig’s application structure is as follow: helloconfig/ MANIFEST.MF classes/ configuration/ lib/ src/ Where:helloconfig/MANIFEST.MF is the manifest file for the HelloConfig application. The code below shows the helloconfig/MANIFEST.MF listing.helloconfig/classes has the HelloConfig compiled classfiles.helloconfig/configuration has HelloConfig’s configuration files.helloconfig/lib has HelloConfig’s required libraries (the libraries required for Commons Configuration usage).helloconfig/src has HelloConfig’s source code files.The following jar command creates helloconfig.jar, the executable sample application jar file:helloconfig> jar cmf MANIFEST.MF helloconfig.jar -C classesThe Commons Configuration required libraries have been downloaded from a Maven mirror site and placed in the /lib folder. The MANIFEST.MF file lists the classpath required for the HelloConfig application and the main class.The following listing is the MANIFEST.MF for the helloconfig sample:helloconfig/MANIFEST.MF Manifest-Version: 1.0 Main-Class: com.helloworld.HelloConfig Class-Path: ./lib/commons-configuration.jar ./lib/commons-beanutils.jar ./lib/commons-collections.jar ./lib/commons-digester.jar ./lib/commons-lang.jar ./lib/commons-logging.jar ./lib/xercesImpl.jar ./lib/xmlParserAPIs.jar ./lib/dom4j.jar Using the manifest file to define the classpath option is preferred over setting the CLASSPATH environment variable. This way, you can set the classpath individually for each application without affecting other applications and without other applications modifying its value. Also, the manifest file keeps valuable information about those libraries required by your application.HelloConfig configuration parameters readerA configuration definition file—config.xml—is required for each HelloConfig environment. Below are the config.xml files’ contents for each available environment:development config.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="configurationdevelopmentenv.properties" /> <properties fileName="configurationhello.properties" /> <dom4j fileName="configurationauthor.xml" /> </configuration> staging config.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="configurationstagingenv.properties" /> <properties fileName="configurationhello.properties" /> <dom4j fileName="configurationauthor.xml" /> </configuration> production config.xml <?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <properties fileName="configurationproductionenv.properties" /> <properties fileName="configurationhello.properties" /> <dom4j fileName="configurationauthor.xml" /> </configuration> In this simplistic Hello World application, HelloConfig is the class reading and displaying the configuration values:HelloConfig.java import com.configmechanism.ConfigurationReader; import org.apache.commons.configuration.Configuration; public class HelloConfig{ public static void main(String[] args) { try { ConfigurationReader configurationReader = new ConfigurationReader(); Configuration config = configurationReader.getConfiguration(); // Printing environment-specific greetings System.out.println(config.getString("env.greetings")); // Configuration parameters from hello.properties System.out.print(config.getString("sample.hello") + " "); System.out.println(config.getString("sample.world")); // Configuration parameters from author.xml System.out.print("author: "); System.out.print(config.getString("name.first") + " "); System.out.println(config.getString("name.last")); System.out.println(config.getString("url")); // Printing environment-specific goodbye System.out.println(config.getString("env.goodbye")); } catch (Exception exc) { exc.printStackTrace(); } } } HelloConfig launch command outlineThe HelloConfig sample application can be executed in one of its three available environments—development, staging, or production. The launch command executes from a folder containing the following required resources:/lib: Folder containing the required libraries/configuration: Folder containing the configuration fileshelloconfig.jar: The executable jar fileBelow is a sequence of commands depicting the execution folder’s contents and the launch commands for each environment with the respective system output:HelloConfig execution C:APPSHELLO>dirVolume in drive C has no label. Volume Serial Number is 7820-4376 Directory of C:APPSHELLO> 10/01/2004 03:59 PM <DIR> . 10/01/2004 03:59 PM <DIR> .. 10/01/2004 03:54 PM <DIR> configuration 10/01/2004 03:54 PM 10,542 helloconfig.jar 10/01/2004 03:54 PM <DIR> lib 1 File(s) 10,542 bytes 4 Dir(s) 15,057,854,464 bytes free C:APPSHELLO>java -Denv=development -jar helloconfig.jar yeap app working in the development environment!!! hello config-mechanism world author: paulo caroli www.caroli.org adios from the development environment; later dude C:APPSHELLO>java -Denv=staging -jar helloconfig.jar all looks good in staging. hello config-mechanism world author: paulo caroli www.caroli.org staging environment end of execution. bye for now. C:APPSHELLO>java -Denv=production -jar helloconfig.jar proper execution in production system. hello config-mechanism world author: paulo caroli www.caroli.org finalizing hello config system. C:APPSHELLO> ConclusionThis article introduced you to a configuration mechanism, a solution for organizing Java applications’ configuration parameters despite multiple runtime environments. Based on a configuration folder structure, a configuration reader enabler, and a simple launching option, the presented solution lessens the complications caused by multiple environments’ configuration values.Paulo Caroli is the J2EE architect at blah!, a provider of cool and exciting infotainment products for wireless carriers that serves a community of more than 4 million worldwide users. Caroli has a master’s degree in software engineering and is a Sun Certified Architect for Java Technology, with expertise in high-performance enterprise application development. To learn more about Caroli, visit his Website http://www.caroli.org. Software DevelopmentJavaOpen Source