Book HomeJava and XML, 2nd EditionSearch this book

Chapter 15. Data Binding

Contents:

First Principles
Castor
Zeus
JAXB
What's Next?

I've tried to run the gamut in what I've covered so far, and even in the order that I've covered it. When I started talking about Java in Chapter 2, "Nuts and Bolts", you had complete control. SAX provided the thinnest of veneers over XML, and basically provided a framework with which to write lots of callbacks. When I moved to DOM and JDOM, you got quite a bit more help, albeit with some loss of power. These tree-based, in-memory models were more convenient, although you had to pay a small price in terms of performance. Moving on to JAXP, you were placed higher up the chain of command, but gained another level of abstraction. At that point, you still had some control, but were working strictly in XML.

Then I shifted gears, and we looked at web publishing frameworks, XML-RPC, SOAP, and business-to-business and web services. This was a far cry from the down-and-dirty approach taken in the first half of the book. While you had immensely more convenience and specialization, you lost a lot of control over how XML was handled, and sometimes didn't see XML at all (like in XML-RPC). This may have left you (as it left me) missing getting your hands dirty a bit. You can't make the subtle tweaks in an XML document's values when working with SOAP, for example, that you could when using SAX or JDOM. However, the convenience of WSDL was nice, and had advantages over typing an element's name wrong in DOM. In short, it left me wishing for a happy medium.

Data binding provides that medium, and I want to take you through the extreme ends of the spectrum before talking about it. In this chapter, I show you a way to get most of the power of a low-level API with most of the convenience of an XML-based application framework (like SOAP). This will probably be something almost everyone can use at some point, and that many can use for a variety of tasks. First, I cover the basic principles that make data binding work. This will be a general overview, as the various data binding packages all have their own specific methodologies. Once you have some grounding, I take you on a quick tour of the two open source data binding APIs, and then Sun's emerging API, JAXB. So, buckle up and dive in.

What About Quick? What About JATO? What About...?

Some of you may be disappointed (or even upset) that I haven't covered your favorite API. However, I didn't make my decisions about which APIs to cover arbitrarily. I chose the two open source APIs that were compatible with JAXB and used the same principles. I selected open source APIs because they are free, and you can use them today; I don't expect you to shell out thousands of dollars for a product like Breeze XML Studio to run my examples[25]. And I selected Castor and Zeus because they use XML standards like XML Schema and DTDs for constraints.

If you're looking for coverage of JXQuick, you won't find it here. The schemas used by JXQuick to represent document constraints and Java classes (QIML, QJML, etc.) are not XML standards, and therefore much less useful in communicating information about your XML to other applications. For this reason, I haven't included it; you can find out more, though, online at http://quickutil.sourceforge.net/view/Main/JXQuick.

The same goes for JATO, located online at http://sourceforge.net/projects/jato, which is more of a scripting language for XML and Java mappings. Because this is less data binding, and more data mapping, it didn't fit well into this chapter or into a JAXB model of doing things. You can check both of these packages out online and make your own decisions. I always recommend you use what's best for your project.

[25]That's not meant to be a knock on Breeze, by the way. I just generally think you should use something that's free rather than the same something you have to pay for. If you want to try a commercial offering, go gor it.

15.1. First Principles

Before diving into specific packages and frameworks that handle data binding, you need to have a basic understanding of what XML data binding is. This turns out to be pretty simple, though, so you'll be coding in no time. First, take a plain old XML document, like the one shown in Example 15-1.

Example 15-1. Homespun tapes XML catalog

<?xml version="1.0"?>

<catalog xmlns="http://www.homespuntapes.com">
  <item id="VD-DOK-GT01" level="4">
    <title>Doc's Guitar Fingerpicking and Flatpicking</title>
    <teacher>Doc Watson</teacher>
    <guest>Pete Seeger</guest>
    <guest>Mike Seeger</guest>
    <guest>Jack Lawrence</guest>
    <guest>Kirk Sutphin</guest>
    <description>Doc Watson, a true master of traditional guitar styles, teaches, 
      in detail, some of the most reuested fingerpicking and flatpicking tunes in
      his vast repertoire, for guitarists at all levels.</description>
  </item>
  <item id="VD-WLX-GT01" level="4">
    <title>The Guitar of David Wilcox</title>
    <teacher>David Wilcox</teacher>
    <description>Create fresh new guitar sounds with rich, ringing voicings! David
      even shows you how to invent your own tunings.</description>
  </item>
  <item id="VD-THI-MN01" level="3">
    <title>Essential Techniques for Mandolin</title>
    <teacher>Chris Thile</teacher>
    <description>Here's a lesson that will thrill and inspire mandolin players at
      all levels.</description>
  </item>
  <item id="CDZ-SM01" level="4">
    <title>Sam Bush Teaches Mandolin Repertoire and Techniques</title>
    <teacher>Sam Bush</teacher>
    <description>Learn complete solos to eight traditional and orignal tunes, each
      one jam-packed with licks, runs, and musical variations.</description>
  </item>
</catalog>

In previous chapters, you learned how to use SAX, DOM, JDOM, and JAXP to access this document. You could manipulate both its structure (the names and ordering of elements, attributes, and other lexical constructs) and its content (the actual data). However, many times you don't need access to the document's structure, and only want to work with its data.

In this latter case, it's overkill and a bit on the annoying side to have to write code that parses your document, extracts the data, and puts it into some format that you can use. It would be much nicer to run a program (or API. . . are you starting to get the picture here?) that did this for you, and produced usable Java classes. In fact, this is exactly what data binding does. With data binding, there are three distinct processes that can occur one after another, in differing order, or in completely unrelated processes. I'll cover each in turn.

15.1.1. Class Generation

The first process, class generation, provides a means to convert an XML document to Java. When data binding converts an XML document into a Java representation, it seeks to provide access to just the data in the document. Additionally, data binding provides some level of meaning to the information in the document. It does this by creating the Java representation with accessor and mutator[26] methods like getItem( ) and setTeacher( ), instead of getElement( ) and setAttribute( ). This makes dealing with documents like the one in Example 15-1 less about Java and more about business logic, which is obviously a good thing. However, these wonderfully Java classes must exist before an XML document can be turned into an instance of one, so I'm back to class generation.

[26]When I say "accessor," I'm referring to what most people call a "getter" method; when I say "mutator," I'm referring to what most people call a "setter" method. However, I also know that a "setter" is a dog, not a Java method, so I'm quick to tell my students not to use that term. Just an idiosyncrasy, I suppose!

Class generation is the process of taking a set of XML constraints and generating Java classes (and possibly interfaces) from those constraints. Think about it this way: XML constraints (like those found in a DTD or XML Schema) are equivalent to Java class definitions. They define the way that data is represented. On the other hand, an XML document is equivalent to an instance of these classes, in that it is simply a set of data that fulfills the contract defined by the document's constraints. Now, read this paragraph again, slowly, and you'll have it.

The data binding frameworks I talk about in this chapter all have a way of representing a document's constraints (usually through a DTD or an XML Schema, but there are also some other options, which I'll get to in the appropriate section). These constraints can then be run through some form of a class generation tool, and you get Java source code ready to compile. This code, once compiled, can be used to generate instance data based on an XML document. You end up with a process akin to that shown in Figure 15-1.

Figure 15-1

Figure 15-1. Class generation in XML data binding

Note that the final product here can be concrete classes, interfaces, interfaces and implementations, or any other permutation of Java classes. In the case of Example 15-1 (assuming that the constraints are represented in some arbitrary form), you might end up with a Catalog interface like this:

public interface Catalog {
    public List getItemList( );
    public void addItem(Item item);
    public void setItemList(List items);
}

Further, you might have an Item interface like this:

public interface Item {
    public String getID( );
    public void setID(String id);
    public int getLevel( );
    public void setLevel(int level);

    public String getTitle( );
    public void setTitle(String title);
    public String getTeacher( );
    public void setTeacher(String teacher);
    public List getGuests( );
    public void addGuest(String guest);
    public void setGuestList(List guests);
    public String getDescription( );
    public void setDescription( );
}

This is quite a bit more useful than writing hundreds of lines of SAX callbacks. It makes working with the document a piece of cake, instead of an exercise in your Java and XML API skills. These are just examples, and not necessarily representative of what you'll get using the APIs covered in this chapter. However, in the following sections, I'll show you exactly how to use the API and let you know what to expect.

15.1.2. Unmarshalling

Keep in mind that once you have a set of generated classes, you still don't have a great many uses for them. Sure, you could use an existing lower-level XML API to read in an XML document, pull out the data, create new instances of the generated classes, and populate them with the data from the XML. But data binding provides all this out of the box, so why bother with that? In fact, data binding frameworks provide for exactly that process. And in that context, unmarshalling is the process of converting an XML document into an instance of a Java class.

NOTE: I've seen, and even been a part of, a lot of confusion about the marshalling/unmarshalling terminology. I'm using the terminology as defined in Sun's latest version of the Java Architecture for Data Binding (JAXB) specification, which is certain to become the standardized vocabulary. In that specification, marshalling is moving from Java to XML, and unmarshalling is moving from XML to Java. I'd stick with those definitions if I were you, as well.

This turns out to be a pretty simple process; you get an XML document, pass it to some tool or class instance in your data binding framework, and you get back a Java object. This is usually a class instance of the top-level Java object representing your document. So, again using Example 15-1, you would get back an instance of the Catalog class. You'll typically need to cast from a java.lang.Object to the specific class that you're expecting, since the framework won't know anything about your classes (because they were generated). But after the class cast, you're ready to work with the object as a Catalog, not as an XML document. You can then use the various accessor and mutator methods to work with the data, and when you are ready to send the document back to the XML from whence it came, you marshal the document.

15.1.3. Marshalling

Marshalling is just the opposite of unmarshalling. It is the process of converting a Java object and its dependent objects into an XML representation. In many cases, marshalling is part of a repeated cycle of transformations to and from XML, and is paired with unmarshalling. As an example, check out Figure 15-2, which is a typical application flow.

Figure 15-2

Figure 15-2. XML data binding application flow

There are two distinct ways to marshal a Java object. The first is to invoke a marshal( ) method on an object; this method is usually generated along with the accessors and mutators during class generation. The method recursively calls the marshal( ) method on each of its dependent objects, until you end up with an XML document. Note that the target XML document does not have to be the same as the original XML; you can easily end up with a vast number of archived XML documents by supplying different filenames to the marshalling process.

A different approach to marshalling, and the one I favor, is having a standalone class that performs marshalling. Instead of invoking marshal( ) on a generated object, you invoke marshal( ) on the standalone class, and pass it the object to marshal. This is useful because it performs the same tasks as illustrated previously, but also allows classes that were not originally unmarshalled from XML to be converted to XML. Think about it this way: data binding, used like this, becomes a persistence framework. Any object with bean-like properties (setXXX( ) and getXXX( )) can easily be converted to XML! You get the power of data binding with the flexibility of persistence. This is a handy combination, and supported by some of the frameworks I talk about in this chapter.

I realize that if you're new to data binding, this may sound a bit confusing and vague; sort of like talking about chemistry. I'd much rather blow some things up (err. . . you know!), so in the rest of the chapter I show you how to use some data binding frameworks. Since I'm going to cover four of these, none of the examples are immensely complex; instead I focus on how to use the class generation, marshalling, and unmarshalling capabilities of each framework. That should be more than enough to get you going.

15.1.4. Use Cases

As a final explanation of data binding and why it's worthwhile, I will give you a small sampling of use-cases. Some of these are best suited for the lower-level APIs like SAX or DOM, and some are perfect for data binding. In Table 15-1, I've listed a common use case, the type of API that would work well, and a short reasoning behind my decision. This should help you see how data binding fits into the XML landscape.

Table 15-1. API use cases

Use case

Well-suited API

Reasoning

XML IDE

DOM or JDOM

Tree-based viewing of XML, as in an IDE, closely follows the tree-based models of DOM and JDOM.

XML messaging server

SAX

Since speed is the most important factor, SAX allows the fastest stream-based reading of messages.

Configuration data

Data binding

The content, rather than the model, is paramount. Data binding saves time and adds convenience to reading configuration data.

XML transformations

DOM or JDOM

Changing both structure and content requires modification of content (rules out SAX) and structure (rules out data binding).

XML messaging client

Data binding

When the message format is known ahead of time, the client can benefit from easy Java objects, as created by data binding.

Obviously, these are just a few common XML applications, but they should give you an idea of when to use a low-level API and when to use a higher-level one.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.