Jato: The new kid on the open source block, Part 1

A new library for converting between Java and XML

Kept separate, XML and Java are environmentally friendly, but sound scientific evidence indicates the effort developers exert to merge them may contribute to global warming. This article, the first of three, introduces the open-source Jato API, a better way to turn XML documents into Java application objects and vice versa. First, we will examine Jato's key features, architecture, and important classes. Then we will develop Jato scripts to perform basic Java-to-XML and XML-to-Java transformations. So get ready to strip out those hundreds of lines of XML parsing code and replace them with a few lines of Jato script!

Read the whole "Jato: The New Kid on the Open Source Block" series:

Note: At the time of this writing, Jato is in Beta 2, with tremendous development work being piled into it. Occasionally, a change is made that will break backwards compatibility. To ensure the article examples work properly, the distribution will include all the samples from this series.

What is Jato?

Jato is an open-source Java API and XML language for transforming XML documents into a set of Java objects and back again. Jato scripts describe the operations to perform and leave the algorithms for implementing the operations to an interpreter. A Jato script expresses the relationships between XML elements and Java objects, freeing the developer from writing iteration loops, recursive routines, error-checking code, and many other error-prone, verbose, and monotonous XML parsing chores.

Jato has many advantages over directly employing traditional Java XML APIs such as JDOM, SAX, or DOM. Those advantages include:

  • Jato encourages XML and Java designs to be optimized for their specified tasks. Well-designed systems have a low degree of coupling, allowing one to make independent changes to portions of a system without it breaking. Indeed, it's a good idea for XML DTD and Java object-oriented design to be developed and deployed independently.
  • With Jato, developers simply express the XML elements that map to or from specific Java classes. The Jato interpreter then implements the necessary parsing and generation algorithms to accomplish the desired actions. As such, you avoid the monotonous, monolithic, and difficult-to-maintain XML parsing and generation code.
  • Using XML to describe transformation to or from XML in Java applications just seems natural. I will never forget the first time an application called for parsing an XML document to create a set of Java objects. After about 150 lines of code, most of the remaining 850 lines consisted of cut-and-paste operations followed by altering element, attribute, class, and method names. Whenever a task involves that much cut-and-paste, it just begs to be automated.

Key Jato features

Jato's design and feature set directly result from implementing real-world projects. Jato is feature-rich, but hopefully not at the expense of usability or readability. Its key features include:

  • Open source: The source code for Jato is freely available for use, modification, and improvement. Please contribute your ideas and energy to the project (see Resources).
  • Completely dynamic: Jato reads Jato scripts at runtime and employs reflection and JDOM to transform between Java and XML. Other APIs that perform similar tasks require the developer to create a schema, generate a set of classes from the schema, compile the classes, and distribute the compiled classes.
  • Supports the JavaBeans naming conventions: If a class contains portions that adhere to the JavaBeans specification, life gets a little simpler.
  • Supports complex constructors and methods: Most real-world applications rely on classes that require nondefault constructors and methods that do not adhere to the JavaBeans specification. Jato can invoke static methods along with multiargument constructors and methods.
  • Macros: Jato script elements can be grouped and invoked within the primary script or other macros. Macros reduce the amount of Jato code required to specify a transformation.
  • Conditional transformations: Transformations can be based on the type of XML element, the presence or value of an attribute, the state of an object, or the phases of the moon.
  • Built on JDOM: Developers can drive the Jato interpreter using any XML parser or generator.
  • Supports namespaces: Many similar APIs do not adequately handle namespaces; Jato does.
  • Custom Jato tags: Developers can easily add new functions to the Jato interpreter. Custom tags enable developers to seamlessly integrate Jato with databases, obtain information from networked applications, perform custom formatting, and handle unique situations.

Jato architecture

Jato consists of several classes and two interfaces, all of which reside in the org.jato package. Let's take a look:

  • JavaToXml: A helper class for performing Java-to-XML transformations from a command line or embedded in an application
  • XmlToJava: A helper class for performing XML-to-Java transformations from a command line or embedded in an application
  • ObjectGenerator: Jato interpreter class for XML-to-Java transformations
  • ObjectHelper: The interface the developer implements to receive instantiated Java objects
  • ObjectAdaptor: An adapter class for ObjectHelper
  • XmlGenerator: The Jato interpreter class for Java-to-XML transformations
  • XmlHelper: The interface the developer implements to provide objects for XML generation
  • XmlAdapter: An adapter class for XmlHelper
  • JatoException: Thrown by a Jato interpreter to indicate an error
  • TagHandler: The interface for implementing custom Jato tag handlers

When specifying a transformation, regardless of the direction, the developer provides:

  • Jato script: XML that expresses how to process XML and Java and generate desired output.
  • Helper class: Provides and publishes important transformation objects and values. The class serves as an adapter class that interfaces the application with Jato.

Figure 1 illustrates the relationship between the ObjectGenerator, ObjectHelper, Jato script, and source XML when performing an XML-to-Java transformation.

Figure 1. XML-to-Java transformation relationships

The ObjectGenerator acts as the Jato interpreter and controls the transformation process. It uses the Jato script to establish a plan for transforming the XML document. The ObjectHelper class receives generated objects marked for publishing in the Jato script through its publish() method.

Figure 2 illustrates the relationship between the XmlGenerator, XmlHelper, Jato descriptor, and Java objects when performing a Java-to-XML transformation.

Figure 2. Java-to-XML transformation relationships

The XmlGenerator acts as the Jato interpreter and controls the transformation process. It uses the Jato script to establish a plan for transforming the Java application objects. The XmlHelper acts as the interface point for the current application. The XmlGenerator requests objects from the XmlHelper and generates an XML document that reflects the state of the application.

Java-to-XML example

The quickest way to understand Jato is to examine sample Java-to-XML and XML-to-Java transformations. The first example translates the system properties obtained using the System class's getProperties() and getProperty() methods into XML. If you have never examined the system properties, Listing 1 serves as an example program that iterates over the properties and prints them to the console:

Listing 1: A program that prints the system properties

import java.util.Properties;
import java.util.Enumeration;
class PrintProps {
   public static void main(String args[]) {
      Properties props = System.getProperties();
      Enumeration e = props.keys();
      String key, prop;
      System.out.println("System properties:");
      while(e.hasMoreElements()) {
         key = (String)e.nextElement();
         System.out.print("\t" + key + "=");
         prop = System.getProperty(key);
         System.out.println(prop);
      }
   }
}

A little verbose, but the reason for that will become apparent when we compare it line-by-line with a Jato script that accomplishes an equivalent task. The application outputs:

System properties:
        java.specification.name=Java Platform API Specification
        awt.toolkit=sun.awt.windows.WToolkit
        java.version=1.2
        java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
        user.timezone=America/Los_Angeles
        java.specification.version=1.2
        java.vm.vendor=Sun Microsystems Inc.
        java.vm.specification.version=1.0
        . . . .

In Listing 2, we see a Jato program that outputs an XML version of the system properties:

Listing 2: A program that performs a Java-to-XML translation

1.  import java.util.Properties;
2.  import org.jdom.JDOMException;
3.  import org.jato.XmlHelperAdapter ;
4.
5.  public class SimpleJavaToXML extends XmlHelperAdapter  {
6.     SimpleJavaToXML() throws JDOMException {
7.        super(sJatoXML);
8.     }
9.
10.    public Object getObject(String key) {
11.       Properties props = System.getProperties();
12.       return props.keys();
13.    }
14.
15.    static String sJatoXML =
16.    "<?xml version='1.0' encoding='UTF-8'?>\n" +
17.    "<Jato:defs xmlns:Jato='http://www.kruel.com/jato'>\n" +
18.    "  <Jato:translate key='prop-names'>\n" +
19.    "    <property>\n" +
20.    "      <Jato:attribute name='name' key='this'/>\n" +
21.    "      <Jato:attribute name='value' invoke='getProperty'" +
22.    "                      class='System'>\n" +
23.    "         <Jato:param type='this'/>\n" +
24.    "      </Jato:attribute>\n" +
25.    "    </property>\n" +
26.    "  </Jato:translate>\n" +
27.    "</Jato:defs>";
28. }

The org.jato.JavaToXml class runs scripts from the command line or allows them to be easily embedded in your applications. To run this script and save it to a file called simple.xml, type this at the command line:

> java org.jato.JavaToXml -x SimpleJavaToXml -s simple.xml -r system-properties

-x specifies the helper class, -s specifies the name of the generated XML document, and -r specifies the name of the root element. By default, the JavaToXml class will use the org.jato.XmlHelperAdapter class as the default helper class and root as the name of the document root element, and will print the generated document to the standard output stream.

The above program outputs:

<?xml version="1.0" encoding="UTF-8"?>
<system-properties>
   <property name="java.specification.name"
               value="Java Platform API Specification" />
   <property name="awt.toolkit" value="sun.awt.windows.WToolkit" />
   <property name="java.version" value="1.2" />
   <property name="java.awt.graphicsenv"
               value="sun.awt.Win32GraphicsEnvironment" />
   <property name="user.timezone" value="America/Los_Angeles" />
   <property name="java.specification.version" value="1.2" />
   <property name="java.vm.vendor" value="Sun Microsystems Inc." />
   <property name="java.vm.specification.version" value="1.0" />
   . . . .
</system-properties>

The sections that follow will dissect the script, but first, let's summarize the generation of the XML file:

  • We wrote a Jato script in XML. The script was embedded in the class using a static variable, though it could just as easily have been stored in a file
  • We wrote a helper class that supplied the system property names
  • We ran the Jato script using the org.jato.JavaToXml class

The Java-to-XML Jato script

The heart of all transformations is the script, so let's dig into Jato starting with lines 16-27 in Listing 2. In this case, I encapsulated the script in a static class variable called sJatoXML, so the entire program exists as a single unit, but the script could have been saved as a separate file. For clarity's sake, here is the script without the Java escape clauses:

1.  <?xml version='1.0' encoding='UTF-8'?>
2.  <Jato:defs xmlns:Jato='http://www.kruel.com'>
3.     <Jato:translate key='prop-names'>
4.        <property>
5.           <Jato:attribute name='name' key='this'/>
6.           <Jato:attribute name='value' invoke='getProperty' class='System'>
7.              <Jato:param type='this'/>
8.           </Jato:attribute>
9.        </property>
10.    </Jato:translate>
11. </Jato:defs>

All Jato scripts share four key characteristics:

  • All Jato XML tags exist within the Jato namespace (line 2 above)
  • All scripts have <Jato:defs> as the root element (line 2)
  • Non-Jato XML tags to be output are simply embedded in the script (lines 4 and 9)
  • Scripts do not specify the ultimate document's root tag

How does this script work? Essentially, it tells the Jato interpreter to:

  1. Get the objects from the helper class keyed by the string 'prop-names' (line 3).
  2. For each object returned, output a property tag with two attributes: 'name' and 'value' (lines 5-8).
  3. Obtain the 'name' attribute using the 'prop-name' object currently being iterated upon by Jato (line 5). Jato will invoke an object's toString() method just like System.out.println().
  4. Obtain the 'value' attribute by invoking the toString() method on the object returned by System.getProperty() method (lines 6-8).

This script demonstrates how Jato integrates with a system through a helper class using the <Jato:translate> tag, allows non-Jato tags to be embedded within scripts, and invokes nonbean and static methods. Like Java, Jato maintains a 'this' reference, referred to in Jato as the current object and accessible using the keyword 'this'. The current object is utilized at line 5 when the 'name' attribute is set for the <property> tag. The current object at line 5 is the object being iterated as part of the <Jato:translate> tag at line 3. At line 7, the current object is used again as the parameter to the System.getProperty(String name) method.

In Table 1, note the similarities between this Jato script and the PrintProps Java class found in Listing 1:

Table 1. Comparison between PrintProps and Jato script
 PrintProps Jato script

 Properties props = System.getProperties();

 Enumeration e = props.keys();

 String key, prop;

 while(e.hasMoreElements()) {

    

key = (String)e.nextElement();

 <Jato:translate key='prop-names'>

  

<property>

    System.out.print("\t" + key + "=");    <Jato:attribute name='name' type='this'/>

    prop = System.getProperty(key);

    

System.out.println(prop);

   <Jato:attribute name='value' invoke='getProperty'

               class='System'>

      <Jato:param type='this'/>

   

</Jato:attribute>

 }

   </property>

 

</Jato:translate>

Moving beyond Jato syntax, let's explore how Jato obtains the objects for the <Jato:translate> tag. When Jato obtains a <Jato:translate> tag, it invokes the helper's getObject() method and passes the value of the 'key' attribute. In our helper class, the getObject() method ignores the 'key' value and simply returns the Enumeration object for the system property names:

public Object getObject(String key) {
    Properties props = System.getProperties();
    return props.keys();
}

Those two lines are the same as the first two lines in PrintProps, shown in Listing 1. Jato understands how to iterate arrays, Enumeration instances, and Iterator instances. The helper class uses the XML string passed to the parent class's constructor to provide the interpreter the Jato script used for the transformation:

SimpleJavaToXml() throws JDOMException {
   super(sJatoXML); //sJatoXML is the static script string
}

The XmlHelperAdapter class provides the following constructors:

  • public XmlHelperAdapter (Document jato)
  • public XmlHelperAdapter (File jatoFile)
  • public XmlHelperAdapter (String jatoXml)

The constructor parameter always creates the Jato transformation script.

To translate Java objects to XML within an application, a program can use the JavaToXml class as follows:

JavaToXml jtox = new JavaToXml();
jtox.setrootOption("system-properties");
jtox.setSaveOption(true, "simple.xml");
jtox.setHelperClass("SimpleJavaToXml");
Document doc = jtox.transform();

The JDOM document returned by jtox.transform() contains the XML representation of the application's objects. In this example, the document has already been saved to the simple.xml file.

XML-to-Java example

As a logical follow-up to the previous example, let's examine a program to translate the system properties XML document back into a java.util.Properties object. We can do this with the SimpleXmlToJava class from Listing 3:

Listing 3: Program that performs an XML-to-Java translation

1.  import java.util.Properties;
2.  import org.jato.ObjectHelperAdapter;
3.  import org.jdom.JDOMException;
4.
5.  public class SimpleXmlToJava extends ObjectHelperAdapter {
6.     public SimpleXmlToJava() throws JDOMException {
7.        super(sJatoXML);
8.     }
9.
10.    public void publish(String key, Object obj, int state)  {
11.       if (state == INITIALIZED_STATE) {
12.          Properties props = (Properties)obj;
13.
14.          props.save(System.out, "System Properties");
15.          System.out.println(props.size());
16.       }
17.    }
18.
19.    static String sJatoXML =
20.    "<?xml version='1.0' encoding='UTF-8'?> \n" +
21.    "<Jato:java-defs xmlns:Jato='http://www.kruel.com/jato' > \n" +
22.    "   <Jato:import>java.util.*</Jato:import> \n" +
23.    "\n" +
24.    "   <Jato:translate elt='system-properties'> \n" +
25.    "      <Jato:object class='Properties' publish='props'> \n" +
26.    "         <Jato:on-elt name='property' action='Jato:invoke' method='setProperty'> \n" +
27.    "            <Jato:param type='string' path='@name'/> \n" +
28.    "            <Jato:param type='string' path='@value'/> \n" +
29.    "         </Jato:on-elt> \n" +
30.    "      </Jato:object> \n" +
31.    "   </Jato:translate> \n" +
32.    "</Jato:java-defs>";
33. }

The org.jato.XmlToJava class runs XML-to-Java transformation scripts from the command line, or allows them to be easily embedded in your applications. To run the script at the command line type:

> java org.jato.XmlToJava -o SimpleXmlToJava -i simple.xml

-o specifies the helper class; -i specifies the XML document to be translated. By default, the XmlToJava class will use default.xml as the name of the input XML document, and the org.jato.ObjectHelperAdapter class as the default helper class.

Once again, let's start our examination by looking at the script, listed at lines 19-32. The script states the following:

  • Import all classes in the java.util package (line 22). The Properties class can be explicitly imported by changing java.util.* to java.util.Properties. If the <Jato:import> tag is omitted, then the 'class' attribute at line 40 must be specified as 'java.util.Properties'.
  • Begin translating the XML to Java when a <system-properties> tag is encountered (line 24).
  • When a tag is encountered, instantiate a Properties object and publish the object to the helper under the name 'props'.
  • For each <property> tag encountered within the <system-properties> tag, invoke the setProperty(String, String) method on the current object (lines 26-29). Then the current object will be the Properties object instantiated at line 40.
  • Get the first parameter as a String using the 'name' attribute for the <property> tag (line 27). The type attribute can be the name of any Java primitive type, a fully qualified class name, or string. The string keyword makes it convenient to create the ever-common java.lang.String objects. The path attribute is the XPath-compliant path to the element or attribute from which the property value will be obtained.
  • Get the second parameter as a String using the 'value' attribute for the <property> tag (line 28).

The helper class contains a single method: publish(). Jato passes objects to that method when a <Jato:object> tag contains the 'publish' attribute. The publish() method tests the state of the object at line 11, for objects are passed to publish() in two states:

  • CREATED_STATE: The object has been constructed but no methods have yet been invoked on it
  • INITIALIZED_STATE: The object has been completely initialized -- that is, all child tags of the <Jato:object> tag have been processed

If the object is in the INITIALIZED_STATE, it is cast to a Properties object, and the contents print to the System.out standard console.

Typical uses for Jato

Java applications routinely use XML to store configuration information, transfer data between heterogeneous databases, and exchange information between processes. In addition to those benefits, Jato could be used as a front-end for XSL, where the XML would be generated using objects that exist as part of a large Java application or JavaSpaces collection. Jato enables the state of a Java application to be easily streamed out in an XML format for performance profiling, technical support, or persistence purposes. In short, whenever a project calls for converting between Java and XML, Jato is the tool for the job.

Conclusion

This article introduced Jato, a nonprocedural XML language for transforming Java objects to and from XML documents. Jato is extremely powerful and capable of making your XML- and Java-based systems more maintainable, robust, and fun to develop. It is especially useful for projects in which the XML schemas and Java APIs change rapidly -- which means just about every new development project.

Jato does not require preprocessing, force XML or Java developers to adhere to arbitrary or proprietary conventions, or require the utilization of specific XML parsers. Simply put, Jato allows developers to create object-oriented Java designs and XML schemas optimized to encapsulate the data and functionality required for a given task.

In future articles, I'll provide detailed information about Jato syntax, features, and uses.

Learn more about this topic

Join the discussion
Be the first to comment on this article. Our Commenting Policies