Java Platform, Enterprise Edition

Java EE Journal

Subscribe to Java EE Journal: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Java EE Journal: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn


J2EE Journal Authors: Jeremy Geelan, Zakia Bouachraoui, Douglas Lyon, Stackify Blog, APM Blog

Related Topics: Java EE Journal, Apache Web Server Journal, XML Magazine, Java Developer Magazine

J2EE Journal: Article

XML Data Binding with JAXB and UBL

XML Data Binding with JAXB and UBL

As more and more industries standardize their data formats around XML, Java developers are challenged to keep up. That's especially true of developers employing a document-centric programming model, where an evolving schema can expose brittleness in your code and leave you wishing for a better solution.

XML data binding relieves the pain of any Java programmer who has ever winced at having to work with a document-centric processing model. Unlike SAX and DOM, which force you to think in terms of a document's structure, XML data binding lets you think in terms of the objects the structure represents. It does so by realizing that structure as a collection of Java classes and interfaces.

This is especially valuable when lots of applications use the same document schemas. Then the data binding approach yields a set of standard classes and interfaces that are reused across all the applications. This saves work since you don't have to write, debug, and maintain code to extract data from XML. There are even more savings if you're developing an application for one of the many industries that have agreed on standard XML Schemas for business data interchange: finance, travel, auto, and retail, to name just four.

This article will look at two new standards: JAXB and UBL.

SAX and DOM
SAX and DOM are among the oldest programming models for managing XML data (perhaps only younger than the "desperate Perl hacker"). SAX (Simple API for XML) is a stream processor for XML that requires you to implement the org.xml.sax.ContentHandler interface. This interface defines a set of callbacks that you register with the SAX parser. The parser calls your methods as it encounters various tokens in the input stream.

SAX is fast, uses memory sparingly, and is useful for accessing just part of a document. It's less efficient, though, if you have to process the document more than once, or need to access document structures randomly, because it runs through the whole document instead of providing any navigational methods.

DOM (Document Object Model) provides a set of APIs for accessing an in-memory representation of the XML document. This representation forms a tree, which the application walks through looking for relevant information. DOM is useful if you need to edit an XML document, or access parts of it randomly. However, DOM implementations tend to be memory intensive, and sometimes even need to store the entire document in memory. This may not even be possible for very large documents.

Frequently, the goal of both SAX and DOM programmers is to initialize domain-specific objects with XML data. For example, given the element:

<Name first="John" last="Smith"/>

a SAX programmer would have to write a content handler and a DOM programmer would have to walk a parse tree to initialize an instance of this domain-specific class:

public class Name {
public String first;
public String last;

public String getFullName() {
return first + " " + last;
}
...
}

Having this instance gives other parts of the application access to XML data using domain-specific logic. However, you get there only by first dealing with the document's structure by way of SAX or DOM. XML data binding, on the other hand, automates this step.

XML Data Binding
XML data binding binds XML constructs directly to objects. Several open source projects for binding XML to Java have taken somewhat different approaches. The superset of their capabilities includes:

  • Generating Java source code from an XML document
  • Generating Java source code from an XML Schema (either DTD or XSD [XML Schema definition language])
  • Generating an XML document from an arbitrary set of Java objects
  • Unmarshaling an XML document (creating in-memory objects)
  • Marshaling an XML document (writing out an XML document from in-memory objects)
  • Validating an XML document, in its unmarshaled or marshaled form

    A recent standard, JAXB, standardizes the XML data binding interface.

    Java Architecture for XML Binding
    Java Architecture for XML Binding (JAXB) was developed in Java Specification Request (JSR) 31. It was written by an industry expert group under the auspices of the Java Community Process. By standardizing the XML data binding interface and providing a conformance test, JAXB allows you to choose among different XML binding implementations without having to rewrite your application. JAXB also comes with a standard implementation, which we'll use to show you how to bind the UBL schema to Java objects.

    UBL
    Universal Business Language (UBL) is an XML-based business language built upon existing EDI and XML business-to-business vocabularies. It's the product of the UBL Technical Committee of oasis. The committee intends to have UBL become an international standard for electronic commerce. If you're a J2EE programmer, there's a good chance UBL will be a part of your future.

    The latest UBL 0.7 release (see References) contains schema, sample XML documents, specifications, and documentation. It's perfect for experimenting with UBL applications. We're going to do just that using Java bindings generated by JAXB from the UBL schema.

    Compiling the UBL Schema into Java Using JAXB
    To compile the UBL schema into Java classes, download the Java Web Services Developer Pack 1.2 (see References). The Java WSDP is a free, integrated toolkit that allows Java developers to build, test, and deploy XML applications, Web services, and Web applications.

    Set JWSDP_HOME to the directory where you installed the Java WSDP. Change to $JWSDP_HOME/jaxb/samples/ubl. Create a directory named test, then run (xjc is JAXB's schema compiler):

    $JWSDP_HOME/jaxb/bin/xjc.sh -d test 0p70/xsd/*.xsd

    (You can also invoke xjc by way of an Ant task.) This creates the packages in test (see Listing 1). (Listings 1-7 can be downloaded from www.sys-con.com/java/sourcec.cfm.)

    By default, xjc puts its output into Java packages with names derived from the schema's targetNamespace.

    Customizing the Package Names
    JAXB gives you control over the binding process with various customizations. These can be inline in the schema by way of XSD annotation elements, or can be put in their own file. In the latter case, JAXB's xjc uses xpath to identify which part of the schema the customization affects. For example, this customization:

    <jaxb:bindings
    schemaLocation="0p70/xsd/CoreComponentParameters.xsd"
    node="/xsd:schema">
    <jaxb:schemaBindings>
    <jaxb:package
    name="org.oasis.ubl.corecomponentparameters"/>
    </jaxb:schemaBindings>
    </jaxb:bindints>

    JAXB Package Name Customization

    puts the Java classes and interfaces created from CoreComponentParameters.xsd in the org.oasis.ubl.corecomponentparameters package.

    ubl.xjb contains this customization and similar ones for each of the UBL schemas. External customization is useful for customizing standard schemas. It allows customization of schemas that are considered read-only. It also allows groups sharing a schema to bind to Java differently based on the needs of each application.

    Create a directory named classes. Then compile the schema like this:

    $JWSDP_HOME/jaxb/bin/xjc.sh -b ubl.xjb -d classes 0p70/xsd/*.xsd

    This creates the packages in classes shown in Listing 2. See Chapter 10 of the Java Web Services Tutorial for more JAXB binding customizations.

    A Typical Binding
    UBL_Library_0p70_Reusable.xsd defines a number of types used throughout the UBL schema. For example, Listing 3 is a simplification of AddressType.

    JAXB binds AddressType to the Java interface shown in Listing 4. You'll find this interface in the directory:

    classes/org/oasis/ubl/commonaggregatetypes.

    This class file contains its implementation.

    classes/org/oasis/ubl/commonaggregatetypes/impl/
    AddressTypeImp.java

    Compiling the Generated Code
    It's easiest just to use Ant:

    $JWSDP_HOME/apache-ant/bin/ant compile-generated

    Creating the Javadoc

    $JWSDP_HOME/apache-ant/bin/ant javadoc

    JAXB's Javadoc is particularly useful since the generated interfaces contain Javadoc comments with the snippet of schema that's bound to them. You can use JAXB's Javadoc customization to add additional documentation.

    The PrintOrder Application
    The UBL sample in Java WSDP 1.2 reads in a UBL order instance, computes subtotals and a grand total, and prints the result to the screen. Sounds simple enough, but there's a lot going on. Here's how you run it:

    $JWSDP_HOME/apache-ant/bin/ant printorder

    This prints the itemized order to the screen, with subtotals for each item and a grand total for the order (see Figure 1).

    PrintOrder contains the main() (see Listing 5). It relies on three facade classes:

  • package samples.ubl.report;
  • import samples.ubl.report.facade.OrderFacade;
  • import samples.ubl.report.facade.OrderLineTypeFacade;
  • import samples.ubl.report.facade.AddressFacade;

    The Facade design pattern provides a simpler, higher-level interface. Typically, that's done to isolate an application from the complexity of the underlying subsystems. Here, our principle motivation is to isolate our application from changes to an evolving schema. Since we just wanted to print a simple report, our facades are read-only.

    A look at printBuyer() in PrintOrder shows that getting the name of the buyer contact (a person, usually) is just a matter of calling OrderFacade's getBuyerContact() method (see Listing 6).

    getBuyerContact() has a simple signature (see Listing 7). In this listing, order is a reference to org.oasis.ubl.order.Order, which is bound to <xsd:element name="Order" type="OrderType"/> inUBL_Library_0p70_Order.xsd. If that binding were to change, for example, such that order.getBuyerParty() returned PartyType, we could make this one-line change to getBuyerContact() without affecting PrintOrder:

    (BuyerPartyType)party = order.getBuyerParty();

    This pattern characterizes the other methods in OrderFacade and the methods in OrderLineTypeFacade and AddressFacade. And none of this code relies on org.w3c.dom or org.xml.sax interfaces.

    Conclusion
    JAXB makes it possible to process XML documents without using SAX or DOM. This saves us time when getting started and over the long haul since we don't have to debug and maintain a lot of tedious code devoted to traditional XML processing. While this is useful for any application that uses XML, it will be especially valuable in those application domains with defined XML Schemas for business data interactions.

    References

  • UBL0p70.zip: http://oasis-open.org/committees/ubl/lcsc/0p70/UBL0p70.zip
  • UBL Technical Committee: www.oasis-open.org/committees/tc_home.php?wg_abbrev=ubl
  • JSR 31: http://jcp.org/en/jsr/detail?id=31
  • Java Community Process: http://jcp.org/
  • JAXB home page: http://java.sun.com/xml/jaxb/index.html
  • Java Web Services Developers Pack 2.0: http://java.sun.com/webservices/webservicespack.html
  • Java Web Services Tutorial: http://java.sun.com/webservices/docs/ 1.1/tutorial/doc/index.html
  • Gamma, E., Helm, R., Johnson, R., and Vlissides, JM. (1998). Design Patterns CD: Elements of Reusable Object-Oriented Software. Addison-Wesley Professional.

    xjc: The JAXB Binding Compiler
    The Java WSDP comes with xjc.sh and an xjc.bat:

    $JWSDP_HOME/jaxb/bin/xjc.sh -help
    Usage: xjc [-options ...] <schema>
    Options:
    -nv : don't validate the input schema
    -extension : allow vendor extensions
    -b <file> : external bindings file
    -d <dir> : output generated files to <dir>
    -p <pkg> : target package
    -host <proxyHost> : set http.proxyHost
    -port <proxyPort> : set http.proxyPort
    -classpath <arg> : where to find user class files
    -help : display this help message

    The build.xml sets up the xjc target like this:

    <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
    <classpath refid="classpath"/>
    </taskdef>

    Joes Office Supply 32 W. Lakeshore Dr Chicago, IL
    Date: February 2, 2003

    Sold To: George Tirebiter
    c/o Bills Microdevices
    413 Spring St
    Elgin, IL 60123

    1. Part No.: 32145-12
    Description: Pencils, box #2 red
    Price: $2.50
    Qty.: 5
    Subtotal: $12.50

    2. Part No.: 78-697-24
    Description: Xeorox Paper- case
    Price: $30.00
    Qty.: 12
    Subtotal: $360.00

    3. Part No.: 091356-3
    Description: Pens, box, blue finepoint
    Price: $5.00
    Qty.: 10
    Subtotal: $50.00

    4. Part No.: 543-165-1
    Description: Tape, 1in case
    Price: $12.50
    Qty.: 3
    Subtotal: $37.50

    5. Part No.: 984567-12
    Description: Staples, wire, box
    Price: $1.00
    Qty.: 10
    Subtotal: $10.00

    6. Part No.: 091344-5
    Description: Pens, box red felt tip
    Price: $5.00
    Qty.: 5
    Subtotal: $25.00

    7. Part No.: 21457-3
    Description: Mousepad, blue
    Price: $0.50
    Qty.: 12
    Subtotal: $6.00

    Total: $501.00

    Common Applications of Binding Customization Resolving Name Collisions
    Since each XML namespace contains six symbol spaces, it's not uncommon for terminals in one symbol space to collide with those in another when JAXB tries to map them to Java. This inlined customization, which handles them automatically, illustrates the technique:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    ...
    <xsd:annotation>
    <xsd:appinfo>
    <jxb:schemaBindings>
    <jxb:nameXmlTransform>
    <jxb:elementName suffix="Element"/>
    </jxb:nameXmlTransform>
    </jxb:schemaBindings>
    <xsd:appinfo>
    </xsd:annotation>
    ...
    </xsd:schema>

    Customizing Names of Classes and Properties
    The text explains how we used an external binding customization to change the name of the packages used for the generated Java code. JAXB also lets you rename classes and properties.

    Setting Global Binding Behavior
    This illustrates only some of the possible global bindings:

    <globalBindings collectionType="indexed"
    fixedAttributeAsConstantProperty="true"
    generateIsSetMethod="true"/>

    This customization:

  • Represents collections as a JavaBean indexed property that also has a length() method (by default, JAXB collection properties are java.util.List).
  • Maps all fixed attributes as Java constants.
  • Generates an isSet method for JAXB properties with a primitive base type (such as int) or base type of List. The isSet method allows you to determine if the getter for an optional property is returning the property's default value or if it is returning a value set within the XML document. This helps you determine what was in the original XML document, although typically, JavaBeans don't care.

    Controlling the Binding of an XML Schema Element to its Java Representation as a Type-Safe Enumeration Class

    <jaxb:globalBinding

    typesafeEnumBase="xsd:string"/> can be used to customize the enumeration members and their values of simpleType with enumeration facets that derive by default from xsd:string (there's a default type-safe enumeration binding for NCName).

  • Comments (1)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.