|
|||||||
|
|
![]() |
|
|
Configuring Applications with XML by David Morris Flexible applications avoid using hard-coded configuration data. That configuration data can describe many parts of an application and help you to build applications that adapt to new challenges with minimal effort. XML is a natural choice for this configuration data because it is widely supported and easy to understand. Unfortunately, it is difficult to find examples that show how to read and manipulate XML documents that support application configuration data. While XML is the most widely supported way to define configuration data, it is not the only way. Other options include property and database files. Java has good support for property files, but support in other languages is limited. Like XML, database files are widely supported; however; database files not as portable as XML files. If you need to support concurrent updates to configuration data, database files are usually the best option. As a first step, you might use XML to store simple configuration information, like JDBC connection properties and user defaults that are read in by your applications. The next step is to manipulate XML data used to store defaults and other information used by your applications. In this article I will walk you through these first two steps and provide you with a Java example. Information that describes other information is known as metadata and helps to make applications even more flexible. The final step is to use XML to store metadata that is used to define parts of your applications, like database structure, process flow, or screen layout. Processing Configuration Data One reason to use XML to store configuration data is that XML works on any platform, and just about any programming language has support for XML. I use Java in my applications to work with XML, but you can adapt these techniques to other programming languages, like RPG IV or C. The ability to process XML in multiple programming languages is most valuable when you are building complex applications that use metadata to describe application components. With Java there are quite a few ways to read and write XML documents. Given a choice, I generally choose JDOM because it is easy to use and does pretty much everything a parser can do. As a side note, it seems that Java Community Process (JCP) projects don't like commitments and JDOM is no exception; interestingly, we are supposed to believe that JDOM is not an acronym and does not stand for Java Document Object Model. There are other parsers, but for most things they are more complex and less intuitive for Java programmers, with few benefits. If you are familiar with the Document Object Model (DOM), you probably recognize from the name that JDOM presents XML documents in a tree format. JDOM is an open-source Java API for parsing, creating, manipulating, and writing XML documents. Unlike DOM, which relies heavily on interfaces to represent nodes, JDOM uses concrete classes for elements, attributes, processing nodes, text nodes, CDATA sections, and the like. Using concrete classes makes it easier to manipulate the underlying XML document; however, JDOM's lack of a generic node interface makes traversing or searching an XML document more cumbersome than it is with DOM. Another alternative to JDOM that I use frequently with configuration data is the Apache Software Foundation's Digester. The Digester project is part of the Jakarta Commons open-source project. One thing Digester can't do is write out an XML document. If you need to read and write XML configuration documents and you are using Digester, you will have to use something like JDOM to handle the output. If your application does not need to write XML configuration data, consider using Digester. Configuring with JDOM There are a number of ways to store and work with property values, and deciding which one is best is challenging. If you use an XML document you have a wide range of tools and platforms to choose from. For this example, I chose to use JDOM because it is simple, lightweight, and provides the capability to read and write XML documents. The example program contains several methods that let you read, write, and list property values stored in an XML document. I use the code from this example to support user screen defaults for servlet-based applications. In those applications, screen value defaults can be set for all users or a specific user. In order to avoid problems associated with concurrent updates, user level defaults are stored by user. The system-wide defaults are stored in a file named properties.xml, and look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<properties>
<active-vendors-only>true</active-vendors-only>
<active-customer-only>true</active-customers-only>
</properties>
This example shows how a system-wide default vendor and customer selection might be coded to support checkbox selections that specify whether active vendors and customers are included. A user's version of this default selection file is stored with the user name appended like this: properties-dmmorris.xml, and would include values set by the user. I won't go into detail about how you would code this in a Web page, but one way I have used this is to place an update default button on prompt screens. Clicking that button allows users to set default values to values shown on any prompt screen. After updating their default values, a user's default file might look like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<properties>
<active-vendors-only>true</active-vendors-only>
<active-customer-only>true</active-customers-only>
<region>South</region>
<office>Atlanta</office>
</properties>
Manipulating XML files with JDOM is fairly straightforward. The example file Defaults contains the source for the Defaults class. The Defaults class refers to a Property class that implements the NamedValue interface. I could have avoided the complexity of the NamedValue interface (and reduced the number of files to build this support), but the flexibility this affords is worth it in this case. If you haven't done so already, download and open the Defaults.java file and follow along while I walk you through this class. There are five methods in the Defaults class that do the real work:
In addition to these five methods, there is a main method that facilitates testing. The main method demonstrates how to read from an XML document containing a properties element with individual properties and values. Existing values are printed using the print method. Following that, any pre-existing heading-value properties are removed using the removeProperty method, then the remaining properties are printed. Next, several new property values are set using the setProperty method. Finally, the remaining properties are written out to an XML document and printed. Installing Defaults and JDOM If you read any of my prior articles that describe the installation of Java packages on the iSeries, the following instructions will seem familiar. The first step is to go to the JDOM and Xerces Web sites and download the latest binary Zip file version to a temporary directory on your PC. After downloading JDOM and Xerces, copy them to your iSeries system and unzip them. You can transfer the downloaded Zip files to your iSeries system using a mapped drive or FTP. The FTP to transfer JDOM and Xerces will look like this: ftp yourSystemHost cd /tmp lcd c:\temp bin put jdom-b8.zip put Xerces-J-bin.2.3.0.zip </bin> Once you have the Zip file on your iSeries, start a Qshell session using the command QSH. Change to the OS/400 Integrated File System (OS/400 IFS) directory, where you want to install JDOM and Xerces and extract the Zip file, using the following commands: mkdir /java mkdir /java/xml cd /java/xml jar xf /tmp/jdom-b8.zip jar xf /tmp/Xerces-J-bin.2.3.0.zip Wait for the dollar sign ($) to appear after each command, which indicates that the command is complete. Symbolic links allow you to make a single file or directory appear to be in two places at once. When you extract the various Jakarta project files you end up with directory names that include the version name. I create a symbolic link that strips off the version name and refer to the stripped-down name in programs and scripts. This makes it easier to upgrade to new versions and to revert to an older version, in case there are problems. For JDOM and Xerces, I created symbolic links to the install directories, using the link (ln) Qshell command, as follows: ln s /java/xml/jdom-b8 /java/xml/jdom ln s /java/xml/xerces-2_3_0 /java/xml/xerces Now create the NamedValue and Defaults classes from the Java source files you uploaded to your iSeries system. Start by moving those files to a /java/demo directory, then create the Java classes using the following Qshell commands: mkdir /java/demo cd /java mv /tmp/Defaults.java demo/Defaults.java mv /tmp/NamedValue.java demo/NamedValue.java export -s CLASSPATH=.:/java/xml/jdom/build/jdom.jar:/java /xml/xerces/xercesImpl.jar:/java/xml/xerces/xml-apis.jar javac demo/NamedValue.java javac demo/Defaults.java It is a good idea to compile the JAR and class files, so when you get a chance, submit the following commands. (Compiling the JAR files improves performance but takes quite a bit of time and processing, so submit the following commands during off hours.)
SBMJOB CMD(QSH CMD('for jar in
$(find L /java/xml/jdom -name
''*.jar'');
do system "CRTJVAPGM CLSF(''"$jar"'')
OPTIMIZE(40)";done'))
JOB(JDOM) JOBQ(QPGMR)
SBMJOB CMD(QSH CMD('for jar in
$(find L /java/xml/xerces -name
''*.jar'');
do system "CRTJVAPGM CLSF(''"$jar"'')
OPTIMIZE(40)";done'))
JOB(XERCES) JOBQ(QPGMR)
CRTJVAPGM CLSF('/java/demo/NamedValue.class') OPTIMIZE(40)
CRTJVAPGM CLSF('/java/demo/Defaults.class') OPTIMIZE(40)
On most systems, compiling the JAR files will take several hours. You can bypass this step if you are anxious to go on to the next step. However, the initial startup time will be much longer. Running the Defaults Demo After uploading and compiling the JAR and class files, try out the Defaults program by running its main method. I start Qshell and set my CLASSPATH and create an empty demo.xml file. I create the XML file using the touch command with the -C options so that the coded character set ID (CCSID) matches the ISO-8859-1 character encoding I specified in the defaults program. After creating the empty file, I run Defaults' main method using the Java command and passing the name of my empty XML file, as follows: export -s CLASSPATH=.:/java/xml/jdom/build/jdom.jar:/java /xml/xerces/xercesImpl.jar:/java/xml/xerces/xml-apis.jar cd /java touch C 819 demo/demo.xml java demo.Defaults demo/demo.xml The output generated by running main will look like this: There are 4 properties: print-headings = true heading-offset = 3 heading-value = Customer heading-value = Name There are 2 properties: print-headings = true heading-offset = 3 There are 4 properties: print-headings = true heading-offset = 3 heading-value = Customer heading-value = Name After running the main method, you will also have the demo.xml document on your system that contains the following XML markup:
<?xml version="1.0" encoding="ISO-8859-1"?>
<properties>
<print-headings>true</print-headings>
<heading-offset>3</heading-offset>
<heading-value>Customer</heading-value>
<heading-value>Name</heading-value>
</properties>
If you have ever used DOM, SAX, or the JAXP interfaces, you will probably see that JDOM is simpler to use. In this case, simpler does not translate to less powerful; JDOM has all of the capabilities of its underlying parser core presented in a more intuitive manner. Metadata and Beyond As with many things in software development, there is more than one way to store application configuration data. There are also different types of application configuration data. When that data starts to describe the data and logic of the application, it becomes metadata, which is data that describes data. Metadata is a very powerful tool that is useful when building flexible applications. Be aware that metadata imposes its own challenges. One challenge that is typical of metadata is that metadata interpreted at runtime will often need to be cached due to a high number of redundant reads. Metadata altered at runtime also imposes transactional requirements that often include locking and concurrency issues. I am not trying to discourage the use of XML documents to store metadata, but for several reasons XML is not always a good choice. Some of the open-source packages that I have worked with provide support that is useful when building metadata described systems. Those open-source projects include Jbind, Castor, Hibernate, and OJB. Jbind supports storing configuration data to XML documents. The other projects use XML documents or database tables to store objects. Each of these projects provides an abstraction layer that helps to minimize ties to a specific database and helps to make Java applications more portable. To find out more about these open-source projects, search for the project name, along with Java. Applications Configured Storing application configuration data in XML helps you to build more flexible applications. XML is a good choice for storing configuration data because it is supported by such a wide variety of programming languages and hardware platforms. This wide support means that Java and RPG IV applications can share and manipulate the same XML configuration data. Application integration is one area where this is becoming more common with XML being used to describe program interfaces. There are several tools that can help you work with XML in your Java programs. One tool to look at is JDOM, which makes it easier to read and manipulate XML documents without sacrificing power. One goal of JDOM is to make working with XML in Java as simple as possible, and no simpler. In other words, JDOM hides complexity where possible, but complex XML constructs are supported and often remain complex. I hope that this brief introduction to XML configuration data and JDOM helps you understand how XML is changing the way applications interact. David Morris is a software architect at Plum Creek Timber Company and started the iSeries-toolkit open-source project. He can be contacted by e-mail at dmmorris@itjungle.com.
|
Editors
Contact the Editors |
| Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |