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).
1 2 Page
Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more