Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Java configuration with XML Schema

A sample XML Schema and Java class show you how

Marcello Vitaletti (Marcello_Vitaletti@tivoli.com), Software engineer, IBM - Tivoli
Marcello Vitaletti works at IBM/Tivoli on software development projects. He cultivated an interest in programming and OO technology during his past experience as a researcher in the area of parallel numerical algorithms for engineering simulations. Contact Marcello at Marcello_Vitaletti@tivoli.com.

Summary:  This article shows how to use a Java XML parser together with the Java language reflection features to create an arbitrary set of named objects according to the content of an XML file. Objects created by the proposed initialization process live in a hierarchical, global namespace. References to these objects anywhere in the code can be obtained by a simple query. The configuration-file XML schema discussed in this article is designed to specify the creation of "parameter objects" as instances of arbitrary Java classes.

Date:  01 Nov 2001
Level:  Introductory
Also available in:   Chinese

Activity:  16498 views
Comments:  

One thing developers usually ponder when starting a new project is the strategy they need to employ to write good parametric code. The behavior of good parametric code can be influenced by parameters that can be set at run time. As an example, a graphics format converter may implement a wide range of different transformations depending on the specified values of several parameters. At run time, this application requires the names of the two files holding the original and the transformed image, respectively. This application may read the transformation parameters from an additional input file.

There are obvious advantages in keeping parameters distinct from other input data sources: The same set of parameters may apply to many different runs, or the specification of working parameters may require an in-depth knowledge of the application's internal structure and algorithms. As an extreme case, parameters could be undocumented and the code distributed together with a default parameter set. By this approach, the authors may enable a different behavior of an application by distributing a different set of parameters.

In the code of a complex application, it should be possible to clearly identify the scope, or context, associated with any given parameter specification. A natural solution for Java applications is to associate a parameter with the program scope where it is being used. The name should then reflect the parameter's position in the hierarchy, which includes:

  • Application
  • Package
  • Class

A parameter whose name is not prefixed by a context qualifier would be assumed to have global scope and refer to the higher level in the hierarchy (Application).

Parameters applying to a specific context (Package or Class) in the code can be constructed by the ordinary Java naming rules. For example,

solver.rk3.p1

and

solver.rk3.timestep.c1

would be the names used to identify a parameter p1 relative to the solver.rk3 package and a parameter c1 relative to the class timestep within the same package.

This naming strategy can be applied to any type of nested logical contexts, not just program unit contexts. This is helpful for maintaining an orderly namespace that avoids name clashes. A logical context that is not associated with a code context will be referred to as a topic. A topic may contain an arbitrary number of nested topics. At the higher level in the name hierarchy (Application), names have no qualifier. Therefore, there is no distinction at the Application level between program-scope parameters and topic parameters. A topic-scoped parameter has a qualified name with topic names running from left to right in descending order of containment, and separated by the "|" character. For example:

Literature|Classics|Odyssey|author

would be the name used to identify a parameter author within a library name context whose topics, from the most to the least general, are Literature, Classics, and Odyssey.

Parameters have an associated type. The following eight basic types correspond to Java built-in types and are also defined as simple types in the XML Schema standard:

  • Boolean
  • Byte
  • Short
  • Integer
  • Long
  • Float
  • Double
  • String

Parameters belonging to the eight basic types require only two character strings for their specification: one for name, and one for value representation. More complex constructs are necessary to define generic Java objects.

XML Schema for configuration files

XML is the natural choice for representing the hierarchical structure of the parameter space. An XML schema file is used to formally define the containment relationships between the program contexts (Package and Class) and the topic contexts. The schema also defines complex types that are necessary to define instances of arbitrary Java classes.

At the root of the proposed schema is the Application element, while the elements mapping the eight basic types (Boolean, String, and Number types) are at the bottom. Basic type parameters are defined within a program scope (Package or Class) or within a Topic by the Parameter complex type. This is illustrated in Figure 1.

The Parameter type

A basic type element surrounded by a Parameter specification defines a new object of the corresponding type within the current context. Package, Class, and Topic are valid contexts that may contain a Parameter specification. You can see from Figure 1 that a Parameter can contain one single element whose type can be any of the eight basic types, or the Reference type. The latter provides the ability to refer to a previously defined object by its name. The semantic of this specification is that a copy of the referenced object should be created, and assigned another name. This is useful when the same complex object (value) is used with different names in different parts of an application. Note that a referenced object can be of any Java type, not just one of the eight basic types.


Figure 1. The Parameter type
The Parameter type

The Object type

Object is a complex XML type defined by the schema. It creates a new instance of an externally specified Java class. This type actually defines the signature of a constructor for the specified class and a matching sequence of values. At parsing time, Java reflection features are exploited to determine the class constructor matching the specified signature and its invocation. As shown in Figure 2, the signature is specified as a sequence. The type of each element in the sequence can be either one of the eight basic types, or the Reference type.


Figure 2. The Object type
The Object type

The ClassMethod and InstanceMethod types

Invocation of a class constructor is not the only way to create instances of a Java class. Generally, object references can be obtained by the invocation of a class method or instance method. As for the Object type, the specification of a ClassMethod or InstanceMethod defines the signature of a valid method for the specified class and a matching sequence of values. However, not all methods return an object reference. The capability of defining method invocations in the configuration file is very important and should not be restricted to methods that return an object reference. For instance, the configuration file could specify the creation of an auxiliary Log object, which all the logging methods in the code will refer to by name. The Log object could require its own initialization, to be performed by an init() instance method. The complete initialization can be performed during the XML configuration file processing where an Object type definition for the Log object would be followed by an InstanceMethod definition, the latter causing the execution of the init() method on the previously defined Log object.

In summary, the semantic of a ClassMethod or InstanceMethod specification implies that the method be called during the configuration file parsing. A new name-object association will be introduced in the current naming context (Package, Class, or Topic) in case an object is returned by the method.

The Property type

Some Java classes are designed to retrieve run-time information from the Properties object returned by System.getProperties(). The specification of a Property element in the configuration file causes the setting of a new name-value property in the Properties table managed by the System class. The Property element definition is conveniently located within the program context (Package) of the Java classes that use them. However, this definition does not create a new named object in the program and topic namespaces. Changing the location of a Property element within a configuration file only affects the relative order by which the element is processed with respect to the other elements.

The Application element

Application is the root element of the schema. A Parameter or Object element defined directly within the Application element has a global scope; its specified name does not inherit any prefix qualification from the container element. The Application element, as shown in Figure 3, can also contain Property specifications and nested containers (Topic and Package).


Figure 3. The Application element
The Application element

The graphic symbols in Figure 3 indicate that an Application element contains an unbounded sequence of elements, the type of each contained element being Parameter, Object, Property, etc. The Topic and Package elements define the respective namespace hierarchies. These namespaces are distinguished by the use of a different separator character ("|" for topic names and "." for Package/Class names). The rules defining the allowed nesting of Topics, Package, and Class elements are illustrated in Figures 4 through 6. The complete schema is reproduced in Appendix A, while a sample configuration file is reproduced in Appendix B.

The Topic type

An element of the Topic type, as shown in the following figure, contains an unbounded sequence of elements. The fully qualified name of the Topic is constructed by adding the "|" separator and the Topic's name attribute to the fully qualified name of the parent context. (Application, which is the root, has a null qualified name.) Each contained element can be:

  • A nested Topic.
  • An element of Parameter, Object, ClassMethod, or InstanceMethod type, whose definition introduces a name-object association relative to the current Topic. The fully qualified name of the new object is constructed by adding the "|" separator and the object's name attribute to the fully qualified name of the current Topic.
  • An element of Property type introducing a name-object association within the System Properties hash table. The name of a property is not prefixed with the fully qualified name of the current Topic.

Figure 4. The Topic type
The Topic type

The Package type

The structure of a Package type, as shown in the following figure, is similar to the structure of a Topic type. The only difference is that a Package can contain nested Class elements in addition to Package elements. The fully qualified name of a Package is constructed by adding the "." separator and the Package's name attribute to the fully qualified name of the parent context. Each contained element can be:

  • A nested Package or Class.
  • An element of Parameter, Object, ClassMethod, or InstanceMethod type, whose definition introduces a name-object association relative to the current Package. The fully qualified name of the new object is constructed by adding the "." separator and the object's name attribute to the fully qualified name of the current Package.
  • An element of Property type introducing a name-object association within the System Properties hash table. The name of a property is not prefixed with the fully qualified name of the current Package.

Figure 5. The Package type
The Package type

The Class type

A Class type terminates the hierarchy of program scopes, as a Class cannot include a nested container element. Otherwise, a Class may include the same elements found in a Package and the same rules apply for the construction of qualified names.


Figure 6. The Class type
The Class type

XMLConfigurator: A configuration utility class

The XMLConfigurator class is designed to provide a convenient interface for handling configuration files that conform to the XML schema reproduced in Appendix A. The class implements a static initialization method that parses one or more configuration files and builds the name-object associations into a TreeMap object. The initialization process may also introduce name-object associations in the System Properties hash table. Other static methods are provided that allow user classes to easily retrieve objects from the TreeMap.

The XMLConfigurator Java sample code, the schema, and a sample configuration file are available for download in Resources.

The class extends org.xml.sax.helpers.DefaultHandler and it implements a customized version of a few methods handling SAX parsing events. The most important ones are startDocument(), startElement(), and endElement(). Default implementations provided by DefaultHandler are retained for other event processing methods.

Static methods are also provided to retrieve parameter objects by their name:

public static Object getParameter     (String key){}
public static Object getClassParameter(Class  obj, String pname){}
public static Object getClassParameter(Object obj, String pname){}

The first method provides the maximum level of generality, requiring that the input string contain the fully qualified name of the parameter object to be returned. The following code fragment shows how to retrieve a string parameter pp relative to sub-topic subTopicB of a topic TopicA:

String p = (String)getParameter("TopicA|subTopicB|pp");

An integer parameter xx relative to the class myapp.util.UtilClass is obtained by:

int x = ((Integer)getParameter("myapp.util.UtilClass.xx")).intValue();

The second and third forms are provided to facilitate the retrieval of program-unit scoped parameters associated to a specific class. In both these forms, the second input parameter, a text string, contains the name of the parameter without qualification. The prefix that is needed to obtain the fully qualified parameter name is internally computed from the input Class object (second signature) or from an instance object of the class (third signature). The following is a sample usage of the third form by the instance method of a class retrieving a parameter yy of type Double:

double y = ((Double)getClassParameter(this, "yy")).doubleValue();

Other convenience methods are implemented for retrieving object instances of the numeric and boolean types by means of their fully qualified name.

public static boolean booleanValue(String key)
public static byte byteValue(String key) {}
public static double doubleValue(String key) {}
public static float floatValue(String key) {}
public static int intValue(String key) {}
public static long longValue(String key) {}
public static short shortValue(String key) {}

The main advantage is that catching exceptions and performing the conversion to the primitive type is done inside the method. Listing 1 shows the retrieval of a b Double whose fully qualified name is mycompany.myproduct.myguess:

Running the code with the sample initialization file

The XMLConfigurator class exploits a logging tool, Log4j, that can be downloaded from jakarta.apache.org (see Resources). Log4j itself can exploit an XML file for its own configuration, so it was interesting to put logging to work in the earliest phase of the XMLConfigurator class static initialization and ensure that there were no "chicken-egg" problems. Logging is a critical function that needs to be active during the initialization phase. Therefore, it seems to be a natural choice to have the logging itself started and initialized by XMLConfigurator. The sample code was developed using version 1.1.3 of Log4j.

There is one line of code that makes the class work only with the Apache XML parser. This can be changed, of course. However, the sample code was developed using version 1.4.3 of Xerces downloaded from xml.apache.org (see Resources).

Once both Log4j and Xerces are installed and the downloaded zip file (see Resources) has been expanded, you can examine the sample batch file run.bat under the path Resources\Export. This file should be changed to match the installation paths of Log4j and Xerces.

The sample code is also available in the form of a VisualAge for Java Version 4.0 repository. Use of the sample code in VisualAge requires that Log4j and Xerces also be available in that environment. This can be done by creating a project for each of these two packages and by importing the jar file into their respective project. (Caveat: you cannot have the IBM XML Parser for Java and Xerces 1.4.3 loaded in the workspace at the same time).

The example XML configuration file in Appendix B specifies the creation of a Locale object that is referenced in the successive instantiation of ResourceBundle objects: something definitely close to the power of an object-oriented scripting language!



Download

DescriptionNameSizeDownload method
Sample code, XML Schema, and configuration filex-jschema-code.zip67KB HTTP

Information about download methods


Resources

About the author

Marcello Vitaletti works at IBM/Tivoli on software development projects. He cultivated an interest in programming and OO technology during his past experience as a researcher in the area of parallel numerical algorithms for engineering simulations. Contact Marcello at Marcello_Vitaletti@tivoli.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology
ArticleID=10617
ArticleTitle=Java configuration with XML Schema
publish-date=11012001
author1-email=Marcello_Vitaletti@tivoli.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers