he XML format has become a de facto standard in contemporary IT work. Amongst all the XML-related technology advances, Java-XML binding and serialization has especially been of use to me because much of the work I do involves back-end business components. Java-XML binding and serialization technology has saved me significant development time and effort?and I know I’m not alone. If utilized judiciously, these technologies not only save time but they will make your system more flexible and responsive to change.
In this article I’ll briefly discuss how Java-XML serialization works and show you how to take advantage of this technology to reduce your effort in processing XML. The resources section (see left column) lists various Java-XML binding technologies, but I’ll be focusing on the open source XStream Java serialization library in this article and the accompanying code sample. You can download the free XStream library and the code for this article from the links in the resources section.
Distinguishing Binding from Serialization
Before digging in to how to use XStream to serialize Java objects, I’ll first clarify the operational difference between Java-XML binding and Java-XML serialization. Both technologies are useful for converting XML back and forth to Java objects, however, Java-XML binding generally entails a pre-processing step that generates a Java source code file from an XML schema or DTD. Most binding libraries are sufficiently robust, such as Sun’s JAXB and Apache’s XMLBeans, that they also generate methods to marshal and unmarshal your XML back and forth to a Java object. So, if you control the build process and can generate your source then this solution is worth considering.
In contrast, Java-XML serialization employs a runtime conversion approach that relies upon the reflection API to convert a Java object to an XML document (and back again). Some libraries, like XStream, include robust APIs to programmatically manipulate the way the XML output is produced to make it more readable. Serialization is less effort to implement because there is no source code generation and compile steps. The downside of this simpler approach is that if the XML isn’t generated with the same library there is no built-in means to ensure that the source XML will correctly deserialize to an instance of your target Java class.
|What You Need
| Java 1.4x or higher.
XStream open source XML serialization library available at http://xstream.codehaus.org/. You’ll need to include the XStream jar file xstream-1.1.2.jar in your classpath.
This article assumes that you’re an advanced-beginner to intermediate Java programmer and somewhat conversant with XML technology.
Like many open source projects XStream is maintained by a distributed team of talented developers. My research indicates that the original author is Joe Walnes, who is one of the smart folks at London-based Thoughtworks. Thoughtworks is the company where Martin Fowler (author of “Refactoring” and “Analysis Patterns“) is Chief Scientist. Whatever its exact origins may be, it’s hard to imagine the library being any easier to use.
While XStream is a serialization library in that an object is converted to a non-Java representation, the classes that you’re serializing don’t need to specify the Serializable marker interface. XStream does its work using an object’s internal fields, which are processed by a Converter-based design that I’ll discuss shortly. In contrast, Sun’s java.beans.XMLEncoder uses the JavaBeans public getter/setter API. When implementing a solution that relies upon reflection there can be a performance penalty but I found the library to be very fast in addition to being thread safe.
If you’re new to the whole concept of Java–XML serialization you probably ought to know that changing class attributes or methods after you’ve serialized a class puts the object’s deserialization seriously at risk. Therefore, it is another usability plus that XStream’s developers made the effort to account for various ‘class change’ scenarios so you’ll know what behavior you can expect depending on what changed and how. This topic is well documented on the XStream web site so I won’t delve into it further here.
Short and Sweet Serialization Code
As you can see in the code snippet immediately below and in the source code accompanying this article, it only requires three lines of code to serialize or de-serialize an object or XML document. Of course, your XML should be well formed and this is especially critical because, as mentioned previously, XStream does not provide any validation. I’ve copied the snippet below from the XStream web site and you’ll notice the caveat about the XPP3 library. This library is a high-performance XML parsing library but I found the DOM parser implementation adequate for my needs. Your mileage may vary.
//Convert a Java object to XMLXStream xstream = new XStream();XStream xstream = new XStream(new DomDriver()); // does not require XPP3 libraryString xml = xstream.toXML(joe);//Convert XML to a Java object using the //same xstream referencePerson joe = xstream.fromXML(joeXML); //joeXML not shown
I’ve encountered one limitation using XStream and this too is duly noted on the project web site: If you’re using a JDK prior to 1.4x you must provide a no-arg default constructor in order to deserialize objects and instantiate them correctly. While I did have to add this plumbing to some existing classes, it wasn’t a big obstacle to overcome.
Among the many impressive aspects of XStream’s implementation are that ease of use and clean XML are obviously highly valued by its authors. When serializing to XML you can alias the fully qualified class name to make the output more readable. As you can see in the snippet below, only one line of code is required to achieve this:
//class name: com.tillman.transport.sport.SportUtilityVehiclexstream.alias("suv", SportUtilityVehicle.class);
With the above line of code the output XML will begin with the element
Understanding XStream’s Design
You’ll observe in the sample code accompanying the article that XStream is capable of serializing a nested object graph and I have had occasion to test this down several levels of depth. Moreover, as mentioned previously, XStream builds its XML using a robust set of converter classes that handle many of the standard Java types that you will encounter, including a fair number of the Collections classes. The XStream reference page describing the converters sums up their role as follows:
The core of XStream consists of a registry of Converters. The responsibility of a Converter is to provide a strategy for converting particular types of objects found in the object graph, to and from XML.
Because the converters are the core of XStream I recommend that you peruse the XStream Converters reference before you start your project. If you have a picture of how the XML will look for a given type or collection it will make your output easier to understand.
Table 1 is an example from the Converters reference. It shows the XML generated using the default Map Converter in the right column and the three classes, any of which will generate that output, in the left column.
Table 1. The Java classes in the left column generate the XML at right when using XStream’s Map Converter.
Also, there is one other fairly obvious shortcut that I’d like to share that saved me some effort. Rather than trying to figure out the XML first, incrementally massaging it into the correct format, let XStream do the heavy lifting. Code your class and write a test harness to generate the serialized XML. Using XStream in “both directions” in your system is the optimal way to ensure that your objects and XML seamlessly convert back and forth. However, in a heterogeneous or a distributed system where you don’t control both ends of the pipe, this obviously isn’t always possible.
So, when should you use Java-XML binding and when is Java-XML serialization more appropriate? If you have some concern about the correctness of your XML input then ensuring your data will produce a valid object only makes sense. If you have control of the build process and generating source code is an option then Java-XML binding will allow you to create your objects such that they can be created and validated against a schema or DTD. On the other hand, if you can perform the serialization and deserialization of your objects using XStream, then this powerful library will definitely save you a lot of time and effort and greatly reduce the complexity of your XML processing.