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


Generating an XML Document with JAXB Generating an XML Document with JAXB

by Deepak Vohra
12/15/2004

An XML Schema represents the structure of an XML document in XML syntax. J2EE developers may require an XML document to conform to an XML Schema. The Java Architecture for XML Binding (JAXB) provides a binding compiler, xjc, to generate Java classes from an XML Schema. The Java classes generated with the JAXB xjc utility represent the different elements and complexTypes in an XML Schema. (A complexType provides for constraining an element by specifying the attributes and elements in an element.) An XML document that conforms to the XML Schema may be constructed from the Java classes.

In this tutorial, JAXB is used to generate Java classes from an XML Schema. An example XML document shall be created from the Java classes. This article is structured into the following sections.

  1. Preliminary Setup
  2. Overview
  3. Generating Java Classes from XML Schema
  4. Creating an XML Document from Java Classes

Preliminary Setup

To generate Java classes from an XML Schema with the JAXB, the JAXB API classes and the xjc utility are required in the CLASSPATH variable. Install the Java Web Service Developer Pack (JWSDP) 1.5 to a installation directory. Add the following .jar files to the CLASSPATH variable.

<JWSDP> is the directory in which Java Web Service Developer Pack 1.5 is installed. Add <JWSDP>/jaxb/bin to the PATH variable. The <JWSDP>/jaxb/bin directory contains the xjc compiler. Add the <JWSDP>/jwsdp-shared/bin directory to the PATH variable. The <JWSDP>/jwsdp-shared/bin directory contains the setenv batch file to set the environment variables JAVA_HOME, ANT_HOME, and JWSDP_HOME.

Overview

JAXB generates Java classes and interfaces corresponding to the top-level elements and top-level complexType elements. In a XML Schema, an element is represented with <xs:element/>, and a complexType is represented with <xs:complexType/>. In this tutorial, an example schema that represents articles published in a scientific journal is compiled with the JAXB binding compiler. This schema has top-level element and complexType declarations. The example XML Schema, catalog.xsd, is below.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="catalog" type="catalogType"/>
 <xsd:complexType name="catalogType">
  <xsd:sequence>
   <xsd:element ref="journal"  minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
  <xsd:attribute name="section" type="xsd:string"/>
  <xsd:attribute name="publisher" type="xsd:string"/>
 </xsd:complexType>
 <xsd:element name="journal" type="journalType"/>
 <xsd:complexType name="journalType">
  <xsd:sequence>
   <xsd:element ref="article"  minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
 </xsd:complexType>
 <xsd:element name="article" type="articleType"/>
 <xsd:complexType name="articleType">
  <xsd:sequence>
   <xsd:element name="title" type="xsd:string"/>
   <xsd:element name="author" type="xsd:string"/>
  </xsd:sequence>
  <xsd:attribute name="level" type="xsd:string"/>
  <xsd:attribute name="date" type="xsd:string"/>
 </xsd:complexType>
</xsd:schema> 
 

Some of the XML Schema constructs are not supported by JAXB. If such unsupported constructs are included in a schema, an error will be generated when you try to generate Java classes from them with xjc. The following schema elements are not supported: xs:any, xs:anyAttribute, xs:notation, xs:redefine, xs:key, xs:keyref, and xs:unique. The following schema attributes are not supported: complexType.abstract, element.abstract, element.substitutionGroup, xsi:type, complexType.block, complexType.final, element.block, element.final, schema.blockDefault, and schema.finalDefault.

Generating Java Classes

The xjc utility is run on the schema to bind a schema to Java classes. Run the xjc utility on the example schema with the command:
>xjc catalog.xsd

Some of the options for the xjc command-line interface are listed in the table:

-nvStrict validation of the input schema(s) is not performed.
-b <file>Specifies the external binding file.
-d <dir> Specifies the directory for generated files.
-p <pkg> Specifies the target package.
-classpath <arg> Specifies classpath.
-use-runtime <pkg> The impl.runtime package does not get generated.
-xmlschema The input schema is a W3C XML Schema (default).

For the example schema catalog.xsd, xjc generates 45 classes, as shown by xjc's output below:

parsing a schema...
compiling a schema...
generated\impl\runtime\ErrorHandlerAdaptor.java
generated\impl\runtime\MSVValidator.java
generated\impl\runtime\NamespaceContext2.java
generated\impl\runtime\UnmarshallableObject.java
generated\impl\runtime\MarshallerImpl.java
generated\impl\runtime\ValidationContext.java
generated\impl\runtime\UnmarshallerImpl.java
generated\impl\runtime\DefaultJAXBContextImpl.java
generated\impl\runtime\ContentHandlerAdaptor.java
generated\impl\runtime\GrammarInfoFacade.java
generated\impl\runtime\UnmarshallingContext.java
generated\impl\runtime\UnmarshallingEventHandlerAdaptor.java
generated\impl\runtime\XMLSerializable.java
generated\impl\runtime\Discarder.java
generated\impl\runtime\PrefixCallback.java
generated\impl\runtime\SAXMarshaller.java
generated\impl\runtime\NamespaceContextImpl.java
generated\impl\runtime\UnmarshallingEventHandler.java
generated\impl\runtime\GrammarInfo.java
generated\impl\runtime\InterningUnmarshallerHandler.java
generated\impl\runtime\ValidatableObject.java
generated\impl\runtime\GrammarInfoImpl.java
generated\impl\runtime\ValidatingUnmarshaller.java
generated\impl\runtime\ValidatorImpl.java
generated\impl\runtime\SAXUnmarshallerHandlerImpl.java
generated\impl\runtime\XMLSerializer.java
generated\impl\runtime\Util.java
generated\impl\runtime\SAXUnmarshallerHandler.java
generated\impl\runtime\AbstractUnmarshallingEventHandlerImpl.java
generated\impl\ArticleImpl.java
generated\impl\ArticleTypeImpl.java
generated\impl\CatalogImpl.java
generated\impl\CatalogTypeImpl.java
generated\impl\JAXBVersion.java
generated\impl\JournalImpl.java
generated\impl\JournalTypeImpl.java
generated\Article.java
generated\ArticleType.java
generated\Catalog.java
generated\CatalogType.java
generated\Journal.java
generated\JournalType.java
generated\ObjectFactory.java
generated\bgm.ser
generated\jaxb.properties

A Java interface and a Java class are generated corresponding to each top-level xs:element and top-level xs:complexType in the example XML Schema. A factory class (ObjectFactory.java), consisting of methods to create interface objects, also gets generated. The ObjectFactory.java class is in this article's sample code file, jaxb-java-resources.zip.

Catalog.java is the interface generated corresponding to the top-level element catalog. An interface generated from a schema element extends the javax.xml.bind.Element class. Catalog.java is illustrated in the listing below.

package generated;
public interface Catalog 
  extends javax.xml.bind.Element, generated.CatalogType
{
}

CatalogType.java is the generated interface corresponding to the top-level complexType catalogType. The CatalogType interface consists of the getter and setter methods for each of the attributes of the catalog element, and a getter method for the journal elements in the catalog element. CatalogType.java is illustrated in the following listing.

package generated;
public interface CatalogType {
    java.lang.String getSection();
    void setSection(java.lang.String value);
    java.util.List getJournal();
    java.lang.String getPublisher();
    void setPublisher(java.lang.String value);
}
  

CatalogImpl.java and CatalogTypeImpl.java are the Java classes generated for the Catalog.java and CatalogType.java interfaces, respectively.

Creating an XML Document from the Java Classes

In this section, an example XML document shall be created from the Java classes generated with JAXB. The example XML document, catalog.xml, is illustrated in the following listing.

<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.w3.org/2001/XMLSchema-Instance"
        section="Java Technology"
        publisher="IBM  developerWorks"> 
    <journal>          
       <article level="Intermediate"  date="January-2004" >
          <title>Service Oriented Architecture Frameworks </title>
           <author>Naveen Balani</author>
       </article>
      <article level="Advanced" date="October-2003"  >
          <title>Advance DAO Programming</title> 
          <author>Sean Sullivan</author>
       </article>
       <article level="Advanced" date="May-2002"  >
          <title>Best Practices in EJB Exception Handling  </title>
          <author>Srikanth Shenoy    </author>
       </article> 
   </journal> 
</catalog>

Create a CatalogImpl class object from the Java classes and marshal the CatalogImpl class object with a Marshaller to construct an XML document.

Creating the Marshaller

First, import the javax.xml.bind package, which consists of the Marshaller, UnMarshaller, and JAXBContext classes. The Marshaller class is used to convert a Java object into XML data. The UnMarshaller class converts an XML document to a Java object.

import javax.xml.bind.*;

Create a JAXBContext. A JAXBContext object is required to implement the JAXB binding framework operations marshal, unmarshal, and validate. An application creates a new instance (object) of the JAXBContext class with the static method newInstance(String contextPath). The contextPath specifies a list of Java package names for the schema-derived interfaces.

JAXBContext jaxbContext=JAXBContext.newInstance("generated");

The directory generated contains the JAXB-generated classes and interfaces.

Create a Marshaller with the createMarshaller method. The Marshaller class has overloaded marshal methods to marshal (that is, convert a Java object to XML data) into SAX2 events, a Document Object Model (DOM) structure, an OutputStream, a javax.xml.transform.Result, or a java.io.Writer object.

Marshaller marshaller=jaxbContext.createMarshaller();

Creating a Java Object for an XML Document: CatalogImpl

To create a Java object, first create an ObjectFactory. An implementation class instance is created with the ObjectFactory. For each of the schema-derived Java classes, a static factory method to produce an object of the class is defined in the ObjectFactory.

ObjectFactory factory=new ObjectFactory(); 

Create a catalog element with the createCatalog method of the ObjectFactory class. CatalogImpl is the implementation class for the interface Catalog.

CatalogImpl catalog=(CatalogImpl)(factory.createCatalog());

Set the section attribute of the catalog element with the setSection method in the CatalogImpl class.

catalog.setSection("Java Technology");

Set the publisher attribute of the catalog element with the setPublisher method.

catalog.setPublisher("IBM developerWorks");

Creating a Java Object for an XML Document: JournalImpl and ArticleImpl

Create a journal element with the createJournal method of the ObjectFactory class. JournalImpl is the implementation class for the interface Journal.

JournalImpl journal=(JournalImpl)(factory.createJournal());

Add the journal element to the catalog element. Obtain a java.util.List of JournalImpl for a CatalogImpl and add the journal element to the List.

java.util.List journalList=catalog.getJournal();
journalList.add(journal);

Create the article element in the journal element with the createArticle method of the ObjectFactory class. ArticleImpl is the implementation class for the Article interface.

ArticleImpl article=(ArticleImpl)(factory.createArticle());

Set the level attribute of the article element with the setLevel method in the ArticleImpl class.

article.setLevel("Intermediate");

Set the date attribute of the article element with the setDate method.

article.setDate("January-2004");

Create the title element in the article element with the setTitle method.

article.setTitle("Service Oriented Architecture Frameworks");

Create the author element of the article element with the setAuthor method.

article.setAuthor("Naveen Balani");

Add the article element to the journal element. Obtain a java.util.List of ArticleImpl for a JournalImpl and add the article element to the List.

java.util.List  articleList=journal.getArticle();
 articleList.add(article);

Similar to the article element created with the procedure explained, add the other article elements to create the example XML document catalog.xml.

Marshalling the Java Object to an XML Document

Marshal the CatalogImpl object to an XML document with the marshal method of the class Marshaller. The CatalogImpl object is marshalled to an OutputStream.

marshaller.marshal(catalog, new FileOutputStream(xmlDocument));

xmlDocument is the output XML java.io.File object, representing the XML document shown at the beginning of this section. JAXBConstructor.java, the program used to create an XML document from the Java classes, is in this article's sample code file, jaxb-java-resources.zip.

Conclusion

JAXB provides a xjc binding compiler to generate Java objects from a schema, which may be subsequently marshalled to an XML document. However, JAXB has a limitation: it does not support all of the XML schema constructs.

Resources

Deepak Vohra is a NuBean consultant and a web developer.


Return to ONJava.com

Copyright © 2009 O'Reilly Media, Inc.