ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


The State of JAXB: Availability, Suitability, Analysis, and Architecture The State of JAXB: Availability, Suitability, Analysis, and Architecture

by Satya Komatineni
05/05/2004

When working with XML in OO languages, there is little doubt that objects provide distinct advantages as compared to SAX, DOM, or raw XML. This process of working with XML and objects seamlessly is called binding. When your chosen language is Java, there are many alternatives available for binding Java and XML. In contrast, in .NET this choice is made for you by Microsoft with a tool called XSD.exe.

Of the solutions available in Java, the Java Architecture for XML Binding, better known as JAXB, seems to have finally turned the corner and is now part of the Java Web Services Developer Pack. For those watching the Java-XML binding over the last few years, a nagging question has been, "What is the current state of JAXB and how well does it represent the java-XML binding space?" This being a "state of ..." article, the audience will be senior architects that want to get a bird's-eye view of JAXB as well as a critical analysis of the strengths and weaknesses of the tool. Additional references to get into the introductory and development details of JAXB are provided at the end of the article.

JAXB Packaging

As stated earlier, JAXB is part of the Java Web Services Developer pack 1.x. This integrated toolkit contains all of J2EE's XML technologies, including SAX, DOM, web services, and others. The instructions for downloading and installing the web services pack identify the sub-packages and OS-by-OS installation instructions. For example, the instructions for the Windows install will tell you to first uninstall the previous version and then install the new release.

Related Reading

XML Hacks
100 Industrial-Strength Tips and Tools
By Michael Fitzgerald

The download is about 30MB and will instruct you to download a 1.4 JVM if you don't have one already. You will be better off installing a compliant JDK before installing JAXB. The JAXB install is fairly smooth after this. JAXB install will use the JDK paths to fix its internal batch files so that they will run properly using the JVM that is specified. I did run into some issues running xjc.bat with JDK 1.4.2, prompting the thought, "Perhaps I should have gone with JDK 1.3.1 instead." But luckily I found a workaround that I will mention later in this article.

The JAXB Release Notes in the distribution identify the necessary .jar files for working with JAXB. This list of .jar files is important when you decide to include the generated Java classes or .jar files and build them in an IDE-based environment such as Eclipse or JBuilder. Chapter 10 and Chapter 11 of the Java Web Services Tutorial works as a user's guide for JAXB.

The distribution includes binaries, the JAXB spec, JAXB API documentation, and sample applications along with source code. The sample directories in the JAXB distribution are especially useful and almost necessary. These sample directories have Ant build.xml files. These are the files that you will most likely end up using to compile your XML solutions into a .jar that you will eventually include in your projects.

Working with JAXB

JAXB makes use of XML schema definitions for generating the bindings between XML and Java. This current dependency on XML schemas is somewhat debated, but in situations where the schemas are readily available, JAXB works quite well in generating the Java classes. Let me start off this discussion by giving an example each of an XML file and an XSD file that I will use in discussing the JAXB architecture.

Sample XML File

<?xml version="1.0" encoding="UTF-8"?>
<folder id="123" name="folder1">
    <file id="123" name="file1">
        <description>desc</description>
        <contents>some text</contents>
    </file>
    <file id="123" name="file1">
        <description>desc</description>
        <contents>some text</contents>
    </file>
</folder>

This XML is a representation of files and folders, say, in a content -management system, where files are individual items inside of a folder. A folder has a database id and a short name as attributes, followed by a collection of files that it contains. Each file has a database id and name as attributes, followed by description and contents for holding descriptive data and the real textual content for that file. To work with this data structure in programs via JAXB, we first need to have an XSD representing the meta-content of this data structure.

Corresponding XSD File

Generating or working with XSD files is not very intuitive. Even when you use tools like xmlspy it can still take some getting used to. I have tried collecting some information in the form of an XML Knowledge Folder to help me with these unfamiliar structures. I end up going to this folder every time I need to create some XSDs. Without these notes, it is hard to remember the XSD syntax, not to mention the additional nuances.

Here is an XSD file that corresponds to the above XML file:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema 
	xmlns:xs="http://www.w3.org/2001/XMLSchema" 
	elementFormDefault="qualified" 
	attributeFormDefault="unqualified">
<!--
***************************************************
* Define a type for the file elment as a 
*      1. collection of two elements description
*         and contents
*      2. an attribute of id that is a string
*      3. an attribute of name that is a string
*      4. Notice that although "file" is a type
*         I refrained from calling it "fileType" as
*         it is vague
*      5. That will result in a Java class called 
*         "fileType" as opposed to the intended
*         class name of "file"
***************************************************
-->
<xs:complexType name="file">
    <xs:all>
        <xs:element name="description" type="xs:string"/>
        <xs:element name="contents" type="xs:string"/>
    </xs:all>
    <xs:attribute name="id" type="xs:string"/>
    <xs:attribute name="name" type="xs:string"/>
</xs:complexType>

<!--
***************************************************
* Now define a folder to be 
*      1. a collection of elements called files of
*         type file
*      2. an attribute of id that is a string
*      3. an attribute of name that is a string
*
* As a folder is the outer-most element I didn't
* think it is worthwhile to publish it as a type
***************************************************
-->
<xs:element name="folder">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="file" type="file" 
	          minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>        
        <xs:attribute name="id" type="xs:string"/>
        <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>
</xs:element>
<!--
***************************************************
* Some additional notes on the XSD
*      1. It is necessary to know basic XSDs when
*         working with JAXB
*      2. Even though a folder is a collection of
*         file types  you can't say so directly in xsd
*      3. you have to walk through the element model
*         and say element/complextype/sequence then
*         the elements
*      4. It is also important to note that attribute
*         is a property  of the complexType and not
*         the element
***************************************************
-->
</xs:schema>

I have annotated the XSD file using comments to clarify syntactical nuances of the XSD to suit an object palette of the intended readers.

XSD to Java Classes

JAXB allows us to go from the XSD to a set of Java interfaces and a supporting cast of other files that will eventually help us work with objects and not XML. As per the documentation, this is accomplished by using a batch file called xjc.bat, which is available in the subdirectory of JAXB\bin. There is an equivalent shell script for UNIX-like operating systems.

xjc.bat -p com.ai.xmltest sample.xsd -d gen

This command line generates the required interfaces and implementation classes from the sample.xsd file as the package com.ai.xmltest and places the results in a directory called gen.

I spent a whole day trying to get this batch file work under JDK 1.4.2 without success. I continue to receive an error message indicating that a content line is not allowed as the first line of an XML file. Lots of references on the Web suggest that this may be a problem at the JDK level. I planned on switching to JDK 1.3.1 to see if that fixed the problem. But instead I have decided to use the more robust route that is used in our project development. This uses the Ant build files that are provided with the JAXB distribution. This approach has the disadvantage of requiring knowledge of Ant and using its tasks in build files. Hopefully, with some examples, the reader can accomplish the same thing.

The Ant Build File to the Rescue

The Ant build file looks something like this:

<?xml version="1.0"?>
<project basedir="." default="jar">
    <!-- if you are not running from
         $JWSDP_HOME/JAXB/samples AND you are using
         your own version of Ant, then you need to specify
         "ant -Djwsdp.home=..." -->
    <property name="jwsdp.home" value="../../.." />
<!--
**************************************************
* In the project I have identified that my goal
* is generate an eventual jar file
* Identify all the needed jar files
**************************************************
-->
    <path id="classpath">
        <pathelement path="." />
        <!-- for use with bundled ant -->
        <fileset dir="${jwsdp.home}"
            includes="JAXB/lib/*.jar" />
        <fileset dir="${jwsdp.home}"
            includes="jwsdp-shared/lib/*.jar" />
        <fileset dir="${jwsdp.home}"
            includes="jaxp/lib/**/*.jar" />
        
    </path>

<!--
**************************************************
* Get hold of the XJCTask that generates the
* Java class files
**************************************************
-->
    <taskdef name="xjc"
        classname="com.sun.tools.xjc.XJCTask">
        <classpath refid="classpath" />
    </taskdef>
    
<!--
**************************************************
* This target compile does the following
* 1. Use sample.xsd in the current directory
* 2. Generate in a sub directory called "gen"
* 3. (You have to Make sure the directory
*    "gen" is created before)
* 4. Use a package name called "com.ai.xmltest"
* 5. All the needed sub directories to suit the
*    package names will be created
* 6. All the needed files will be created
**************************************************
-->
    <target name="compile">
        <echo message="Compiling the schema..."/>
        <xjc schema="sample.xsd"
            target="./gen" package="com.ai.xmltest"/>
    </target>
    
<!--
**************************************************
* This target Javacompile compiles the Java into
* classes. This activity depends on the previous 
* "compile" activity. It takes the sources 
* from "gen" and creates the classes into
* "gen" as well
**************************************************
-->
    <target name="Javacompile" depends="compile">    
        <Javac srcdir="./gen"
            destdir="./gen" debug="on">
            <classpath refid="classpath" /> 
        </Javac>
    </target>
    
<!--
**************************************************
* Finally the "jar" activity will jar up the output 
* from the previous activity
* You can specify the zip or jar file that you want
* In my case I have placed the output in a sep directory
* I used zip extension so that pkzip will pick it up easily 
* to verify the output
**************************************************
-->
    <target name="jar" depends="Javacompile">
        <jar destfile="c:\work\xmltest.zip"
            basedir="./gen">
        </jar>
    </target>
    
</project>

You can change the XSD file references and other directory references to make this file work for you. To run this file, you can name this file build.xml and run Ant from that directory. Here is a batch file that runs Ant on this file.

set path=C:\jws-pack-13\apache-ant\bin
set Java_HOME=c:\jdk142
ant

This batch file will set the path to where Ant is available. As you can see, the JAXB distribution includes this in the apache-ant subdirectory. You also need to set the Java_HOME path variable. Then run this batch file in the directory where you have the build.xml and XSD files.

The end result of running this batch file is a .jar file with all of the generated classes.

Summary of the Compilation Process

Compared to .NET, the compilation process is quite painful until you get a hang of the Ant build files. So expect to spend some time to get yourself familiarized with Ant. One good thing about the Ant build files is that you can generate the .jar file directly from the XSD files. This will give you a nice packaged .jar file that you can include in your IDEs and the runtime.

Story of the Generated Classes

It will be interesting to see what the generated classes look like and how they compare with .NET's generated classes.

//************************************************
// Folder classes
// Notice the following
// 1. There is an intermediate class called FolderType
// 2. The contained files is returned as List interface
// 3. This is quite useful comaped to .NET which
//    returns an array 
//************************************************
package com.ai.xmltest;
public interface FolderType 
{
    Java.lang.String getName();
    void setName(Java.lang.String value);

    Java.lang.String getId();
    void setId(Java.lang.String value);
    Java.util.List getFile();

}
public interface Folder
    extends Javax.xml.bind.Element,
            com.ai.xmltest.FolderType
{
}

//************************************************
// File classes
// Notice the following
// 1. See how it is possible to generate
//    "isSet" methods
//************************************************
package com.ai.xmltest;
public interface File {
    Java.lang.String getDescription();
    void setDescription(Java.lang.String value);

    boolean isSetDescription();
    void unsetDescription();

    Java.lang.String getContents();
    void setContents(Java.lang.String value);

    Java.lang.String getName();
    void setName(Java.lang.String value);

    Java.lang.String getId();
    void setId(Java.lang.String value);
}

We can conclude a few things from the generated classes. JAXB generates interfaces as opposed to concrete classes. Also, JAXB sometimes appends type as part of a classname. This matter falls under the topic of customizing the Java class generation and is discussed in one of the included references. Another important thing to note is that the children of a container-like folder are represented using List. This is quite convenient, as one can use this object to add any number of items as children. This seems obvious until one examines the class generation in the .NET world, where this object is represented using typed, fixed-length, un-instantiated arrays. These fixed-length arrays are quite distracting. On the other hand, one problem with the interface-based approach is that you can't add constructors to these interfaces to force the mandatory arguments to these classes. With that, let us take a look at the generated .NET classes

Comparing to .NET class generation

using System.Xml.Serialization;
namespace XMLSerializationTest 
{
    /// <remarks/>
    [System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
    public class folder 
    {
        //Default constructor
        public folder() {}
        public folder(string inId, string inName,
                      int numberOfItems)
        {
            id = inId;
            name = inName;
            files = new file[numberOfItems];
        }
        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("file")]
        public file[] files;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string id;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name;
    }

    /// <remarks/>
    public class file
    {
        public file(){}
        public file(string inId, string inName)
        {
            id = inId;
            name = inName;
        }
        /// <remarks/>
        public string description;
    
        /// <remarks/>
        public string contents;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string id;
    
        /// <remarks/>
        [System.Xml.Serialization.XmlAttributeAttribute()]
        public string name;
    }//eof-class
}//eof-namespace

I have modified the generated .NET classes slightly. This is possible in .NET because the generated classes are concrete classes with public variables. I have added constructors to both classes so that mandatory arguments can be passed in during the construction phase. There is one drawback I have mentioned before with the .NET generated classes: for containment, .NET uses typed, fixed-length, un-instantiated arrays. For example, the variable files[] is just a reference. To use this variable you have to instantiate an object memory for it. You can see this in the constructor of the folder class.

JAXB Allows Customization of Class Generation

The generated Java classes are customizable using either inline annotation or external annotation files. These external files are XML files that identify a node of the XSD and provide additional configuration for that node/element. In the .NET world, a similar goal is accomplished through .NET's attribute technology. Those familiar with this .NET technology should be able to draw parallels between the two approaches.

Example of an Inline Annotation

The subject of customizing JAXB bindings is covered in much more depth by Sayed Hashimi in his ONJava article, "Understanding JAXB: Java Binding Customization." Architecturally, it will be illustrative if I can show an inline annotation to add an isSet method to the XSD that we have.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
            xmlns:jxb="http://Java.sun.com/xml/ns/JAXB"
            jxb:version="1.0"
            elementFormDefault="qualified" 
            attributeFormDefault="unqualified">
<!--
**************************************************
* Notice the XSD annotation elements
**************************************************
-->
<xs:complexType name="file">
    <xs:all>
        <xs:element name="description"
            type="xs:string">
            <xs:annotation>
               <xs:appinfo>
                  <jxb:property
                    generateIsSetMethod="true"/>
               </xs:appinfo>
            </xs:annotation>
        </xs:element>            
        <xs:element name="contents" type="xs:string"/>
    </xs:all>
    <xs:attribute name="id" type="xs:string"/>
    <xs:attribute name="name" type="xs:string"/>
</xs:complexType>

<!--
**************************************************
* folder definition
**************************************************
-->
<xs:element name="folder">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="file" type="file" 
	         minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>        
        <xs:attribute name="id" type="xs:string"/>
        <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>
</xs:element>
</xs:schema>

The inline bold section will instruct the JAXB binding generator to generate a check method for setting the description property of the file class. This scenario is similar to the null values in databases: a column in a database can be checked not only for its value but to see if it has been set at all.

Example of an External Annotation File

JAXB also allows extensive customization using external files as well, to cover the cases where it is not possible or convenient to modify the XSD document. Here is an example of an external file that does the same thing as the above XSD annotation.

<jxb:bindings version="1.0"
               xmlns:jxb="http://Java.sun.com/xml/ns/JAXB"
               xmlns:xs="http://www.w3.org/2001/XMLSchema">
...some stuff
    <jxb:bindings node="//xs:complexType[@name='file']">
          <jxb:bindings node=".//xs:element[@name='description']">
                  <jxb:property generateIsSetMethod="true"/>
          </jxb:bindings>
    </jxb:bindings>
...some more stuff
</jxb:bindings>

I have included just the relevant section for the description node. For the actual file syntax look in the JAXB\samples\ subdirectory in the JAXB distribution.

One can also alter the original XSD to suit the needs of customization. This aspect is also covered in some detail in the above-mentioned article. These issues are architecturally significant, as one can get a sense of how JAXB works from a high-level perspective.

What Can Be Customized?

Now we know that JAXB can be customized, let us examine what aspects can be customized. Package names can be customized. Derivation can be controlled, to some extent. Method generation can be customized. The other customizable aspects include:

Like many other APIs in J2EE, JAXB is designed so that there can be more than one implementation that adheres to the same defined interface. JAXB also provides a range of validation services whereby the structure of XML and Java objects can be directly checked against a schema document. JAXB also seems to have been well thought out, offering multiple input and output mechanisms that include input/output streams, URLs, DOM, SAX, and javax.xml.transform.SAX.SAXSource. Whether you like it or not, JAXB uses a factory-based approach to create Java objects that are capable of working with XML. JAXB also allows the manipulation of the marshaller to tweak the XML output.

Programming Example Using JAXB

Let me show you a client program using the JAXB-generated Java classes.

//************************************************
//* Package and includes
//************************************************
package com.ai.xmltest;
import Java.util.*;
import Javax.xml.bind.*;

//************************************************
//* main class
//************************************************
public class XMLTest 
{
//************************************************
//* Get a JAXBContext one time
//************************************************
    private static JAXBContext jc = null;
    public static void main(String[] args) 
    {
        try
        {
            System.out.println("Establish the context");
            jc = JAXBContext.newInstance("com.ai.xmltest");
            
            System.out.println("Create a Java object" +
                "and stream it out as xml");
            JavaToXML();
            
            System.out.println("Read an xml file as a Java " +
                "object and stream it back as xml");
            xmlToJava();
            
        }
        catch (JAXBException x)
        {
            x.printStackTrace();
        }
    }//eof-main

//************************************************
//* Java to XML
//************************************************
    public static void JavaToXML() 
                        throws JAXBException
    {
        ObjectFactory of = new ObjectFactory();
        File file = of.createFile();
        file.setId("1");
        file.setName("file1");
        file.setDescription("description");
        file.setContents("longtext");
            
        Folder folder = of.createFolder();
        folder.setId("1");
        folder.setName("folder1");
        List fileList = folder.getFile();
        fileList.add(file);
        
        printFolder(folder);
    }
//************************************************
//* XML to Java
//************************************************
    public static void xmlToJava()
                    throws JAXBException
    {
        Java.io.File xmlfile = new Java.io.File(
            "C:\\satya\\data\\eclipse\\JAXB\\sample.xml");
        
        Unmarshaller um = jc.createUnmarshaller();
        Folder folder = (Folder)um.unmarshal(xmlfile);
        
        printFolder(folder);
    
    }
    
//************************************************
//* Print support
//************************************************
    public static void printFolder(Folder folder)
                    throws JAXBException
    {
        Marshaller m = jc.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                      new Boolean(true));
        m.marshal(folder,System.out);
    }
}//eof-class

A JAXB client typically works with three objects: context, marshaller, and unmarshaller. The process is quite straightforward and easy. Nevertheless, obtaining the JAXBContext is quite fishy. Actually, getting provider classes for a given API throughout the J2EE API is quite inconsistent. In this case, you have to pass the package names to the static function of newInstance to locate the provider for the JAXBContext. Passing package names for locating implementation objects seem odd.

Also notice how we have to use the ObjectFactory to obtain the instances of the Java classes. In addition, we have to use a series of set methods to populate these objects. A constructor would have been better for mandatory arguments. But JAXB being interface-centric, this is not really possible. Let us take a look at how .NET does the same thing.

Programming Example Using .NET

//************************************************
//* packages and imports
//************************************************
using System;
using System.Data;
using System.Collections;
using System.Xml.Serialization;
using System.IO;
namespace XMLSerializationTest
{
    class DBTest
    {
        [STAThread]
        static void Main(string[] args)
        {
            //Read the xml from a file into an object
            //Serialize the xml back to output stream
            folder f = xmlToCode();
            System.Console.WriteLine(
                "XML to code to print stream");
            printObjectAsXML(f);

            //code to xml
            f = codeToXML();
            System.Console.WriteLine(
                "Code to XML to print stream");
            printObjectAsXML(f);

        }//eof-main
//************************************************
//* xml to code
//************************************************
        static folder xmlToCode()
        {
            FileStream fs = null;
            try
            {
                fs = new System.IO.FileStream("sample.xml",
                    System.IO.FileMode.Open);
                //returns the folder object    
                XmlSerializer s =
                    new XmlSerializer(typeof(folder));
                folder o = (folder)s.Deserialize(fs);
                return o;
            }
            finally
            {
                if (fs != null) 
                {
                    fs.Close();
                }
            }
        }
//************************************************
//* code to xml
//************************************************
        static folder codeToXML()
        {
            //Create a folder
            //id is 1, name is folder1,
            // and holds two items
            folder folder = new folder("1","folder1",2);

            //dotnet uses a typed array to bind to xml
            //children. This is a nuisance as you need
            //to know the length of the array to
            //populate it before hand. In addition it
            //is the programmer's responsibility
            //to initialize the array
            file file1 = new file("1","file1");
            file1.contents="file1 conent";

            file file2 = new file("1","file2");
            file2.contents="file2 contents";

            folder.files[0]=file1;
            folder.files[1] = file2;
            return folder;
        }
//************************************************
//* print support
//************************************************
        static void printObjectAsXML(Object obj)
        {
            XmlSerializer x =
                new XmlSerializer(obj.GetType());
            x.Serialize(System.Console.Out,obj);
        }
    }//eof-class
}//eof-namespace

One main difference is that you can instantiate .NET objects directly without any factories. You can add constructors for mandatory arguments. One odd thing with .NET is that it uses arrays. This requires a workaround for populating child objects. JAXB has a better approach, where they use dynamic list objects. But otherwise, the .NET's approach is much more coder-friendly and fairly separated from the XSD requirement, making code more central. In JAXB, XSD is more central to the process.

Experiences with JAXB

When our team looked into a solution for processing XML messages, JAXB seemed like an obvious choice, as it is part of the Sun J2EE infrastructure. XSDs were not an issue, as we already have XSDs for the XML messages that we deal with. These XSDs are fairly complex. We are quite pleased with the JAXB handling of our XSDs. JAXB also seems to process the XML messages quite efficiently. JAXB is also found to be quite reliable.

XSDs being such an integral assumption of JAXB, the validation of data structures against an XSD is quite strong and a useful element in the solution. The documentation of JAXB also goes on to say that one can use the RelaxNG syntax for schemas via an available extension.

My Impressions of JAXB

Although the team is quite pleased with JAXB, I see some issues with JAXB for broader architectures. At the outset, JAXB requires a schema document (at least in the current release). This means you cannot take an XML document and try to map it into a similarly structured Java class. More importantly, these Java classes need to be generated by JAXB. This is because the serialization and unserialization are accomplished through JAXB's hidden implementation classes and not through reflection. This approach might be more efficient, but from a maintenance and expediency perspective, this solution doesn't fare very well.

JAXB prides itself on allowing for multiple implementations. I am not sure if this requirement hasn't stretched JAXB to be more complex than it needs to be. This idea resulted in interfaces and implementations for the binding generated classes. This makes it hard to change the generated classes — they're usually not touchable for any modifications. So the final authority is the XSDs and not the java classes. Another consequence of this approach is that the generated classes are more numerous and more complex compared to .NET's binding approach.

Due to the nature of the interfaces, one cannot new content objects: you have to use a factory. This can be very tedious, as your content hierarchy involves getting new objects all the time. For every object creation you have to go to the factory.

The validations and extensions to the default behavior are a bit complex. For example the inline annotations and external annotation files for customizing binding are a bit more complex than .NET. Given that Java 1.3 does not have support for meta attributes this may be the only reasonable solution.

What Are Others Saying About JAXB?

Architecturally, it is also worth noting the sentiments of others on the subject of JAXB. The primary complaint with JAXB seems to be the mandatory reliance on the W3C schema in the current release. For instance, in .NET, you can take an arbitrary C# object and serialize it as XML. The object doesn't have to be generated from a schema. Even though the original object may have been generated from the schema, you can tweak the object, add a couple of fields, and serialize it as XML.

The second problem is the nature of the code generated by JAXB. JAXB generates interfaces representing the content (domain) objects. This means when it is time to create the object tree, you can't just instantiate these objects. You have to use the ObjectFactory created by JAXB to create each new object. This can be a bit tedious compared to creating other objects with a typical new.

As I said, JAXB generates interfaces that you can't change or touch -- if you do, then the implementations will be out of whack. It is almost as if these generated classes are untouchable. Any necessary changes have to be made to the XSDs, and changing XSDs is not necessarily child's play. Perhaps with the help of xmlspy this might be easy enough. But changes to XSDs can result in different styles of Java code generation. For simple tweaks, this seems to be a heavy-handed approach. That said, ne can also argue that the JAXB approach is better, as the "truth" is always maintained in one place: the XSD file.

There is one more issue with the generated interfaces. It might be minor, but it's worth mentioning: because of the get/set methods of the interfaces, the interface definitions tend to be verbose, clouding the structure of the data (not to mention bloating the size of the generated code). In contrast, .NET produces classes with public properties. Although one could argue with the sanity of public properties, the approach has a practical advantage to it: clarity.

Although the architecture of interfaces, implementations, and multiple providers is seen in general as an advantage the resulting solution seem to be unnecessarily complex for general usage. Perhaps this is a difficult point to argue as perhaps JAXB might come out to be wiser in the long run for the provided flexibility.

In general, the XML binding infrastructure in the Java space seem to be much more diversified and involved compared to .NET's approach. Having worked with both .NET's XML binding and JAXB's binding, .NET seem to be lot more easier and cleaner for the simpler and straightforward cases. Nevertheless, I am not sure how they fare in cases with complex and more flexible requirements.

Bottom Line

JAXB and Castor seemed to be the primary contenders in the Java space until recently. With the recent release and inclusion of JAXB into the web services pack, I believe more and more people are going to be using JAXB. Also once one accepts the fact that they have to work with XSDs to work with JAXB (for now) one can always find workarounds for existing Java classes.

As pointed out in the "Experiences with JAXB" section, it seems to be stable, reliable and usable for day-to-day operations. A few of my colleagues, Sayed Hashimi and David Goyette, have used JAXB extensively for XML message processing and also for configuration files. Their feedback is that both are quite thrilled with the results and their lives are lot easier now with JAXB, compared to their earlier use of a SAX parser for the same project.

Nevertheless, it pays to know the following while working with JAXB:

References

  1. Online JAXB question/answer forum at Sun
  2. JAXB home page for articles, what's new, and JAXB packaging information
  3. JAXB Executive summary from Sun
  4. The JAXB API
    This article by Kohsuke Kawaguchi explains the overview, architecture and potential limitations of JAXB. This is a good read.
  5. "Java architecture for XML binding"
    This is the next-level reading from the executive summary from Sun. It has some sample code identifying the key features, but doesn't have the sample code that might be complete enough for you to be productive.
  6. JAXB RI RELAX NG extension
    Supposedly a better way to deal with XML and Java. The reader is advised to do further research.
  7. XML Knowledge Folder
    As XSDs are so crucial to work with JAXB, this above link has a collection of resources that will help with XML-related technologies (including authoring basic XSDs) to get you started on JAXB.

Satya Komatineni is the CTO at Indent, Inc. and the author of Aspire, an open source web development RAD tool for J2EE/XML.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.