Main Page

Previous Section Next Section

The JAXB API

The JAXB specifications defines three basic packages, shown in Table 13.2. Let us look at the javax.xml.bind package in detail.

Table 13.2: JAXB Packages

javax.xml.bind

Defines the interfaces and classes to be used by developers. Deals with marshalling, unmarshalling, and validation.

javax.xml.bind.util

Contains useful utility classes for use by developers.

javax.xml.bind.helper

Not intended to be used by developers. The package provides default implementations of some interfaces in the javax.xml.bind package, for providers to use.

JAXBContext

The entry point for any developer code into JAXB will be a JAXBContext object using the newInstance() method:

JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema" );

The JAXB context initializes the underlying JAXB runtime with the appropriate factory information. The file named jaxb.properties is searched for in the classpath and the class indicated by the javax.xml.bind.context.factory property and is used to create the context. The context is passed the package name, which contains the binding information (multiple package names can be specified using the colon separator, ":"; this allows JAXB to manage the multiple schemas at one time).

The packages specified must contain binding information generated by a single vendor (who provides the JAXB implementation). With multiple packages, the same context can be used to marshall and unmarshall multiple XML documents from different schemas in a single invocation. The JAXB implementation will ensure that each package on the context path has a jaxb.properties file containing a value for the javax.xml.bind.context.factory property and that all these values resolve to the same provider-in short, that the context is specific to a JAXB implementation.

As mentioned earlier, the binding compiler generates the interfaces corresponding to schema constructs as well as the implementation for such interfaces. This raises the question of how multiple implementations can be used in a single application-for example, where an application component must be packaged and distributed and may potentially be used with other application components using another vendor's JAXB implementation. To facilitate such situations, different JAXB contexts would need to be created for different packages and possibly with different class loaders, using the alternate newInstance() method:

JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema", myclassloader );
Unmarshaller

The javax.xml.bind.Unmarshaller is responsible for unmarshalling XML documents (which are based on the schema) into Java object representations. An Unmarshaller is created from a JAXBContext, using the createUnmarshaller() method:

    JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema" );
// create an Unmarshaller
    Unmarshaller unmars = context.createUnmarshaller();

Once created, the Unmarshaller can be applied to many different XML sources using convenient methods, as Table 13.3 shows.

Table 13.3: Unmarshalling from Different Sources

Unmarshalling method

Unmarshall from

public void Object umarshall(java.io.File f)

XML data from a file

public void Object unmarshall (org.xml.sax.InputSource source)

From the specified SAX InputSource

(See Chapter 9)

public void Object unmarshall (java.io.InputStream is)

From any InputStream

public Object unmarshall (org.w3c.dom.Node node)

From a W3C DOM tree

(See Chapter 9)

public void Object unmarshall (javax.xml.transform.Source source)

From the XML Source object.

(See Chapter 9)

public void Object unmarshall(java.net.URL url)

From a network URL

The Unmarshaller has two other important functions:

  • Performing validation during unmarshalling, to verify that the XML conforms to the schema. Upon invoking the setValidating(true), the Marshaller instance will be marked as a validating unmarshaller, and the JAXB provider performs XML validation against the schema used to generate the binding information:

    JAXBContext context = JAXBContext.newInstance("com.flutebank.schema");
    // create an Unmarshaller
        Unmarshaller unmars = context.createUnmarshaller();
        unmars.setValidating(true);
    // Any XML instance unmarshalled will now be validated against the schema used by the
    // binding compiler
    
    
  • Registering application-defined event handlers that are notified of validation events. Developers write the event handlers by implementing the javax.xml .bind.ValidationEventHandler method and registering this handler with the Unmarshaller, using the setEventHandler method:

    JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema" );
      // create an Unmarshaller
        Unmarshaller unmars = context.createUnmarshaller();
        MyValidator validr=new MyValidator():
        unmars.setEventHandler(validr);
    

The default validation handler in JAXB will terminate processing upon encountering the first fatal error. So if your application must recover gracefully or conditionally process the XML, consider overriding the default handler. This is analogous to the SAX handlers in Chapter 9.

Marshaller

The javax.xml.bind.Marshaller can be used to marshall object representations into XML format. The XML is based on the schema passed to the binding compiler and used to generate the initial Java bindings.

The marshaller is also created from the context:

JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema" );
   // Other code here
   Marshaller mars = context.createMarshaller();
   mars.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
   mars.setProperty (Marshaller.JAXB_SCHEMA_LOCATION,
                      "http://www.flutebank.com/schema purchaseorder.xsd");
mars.marshall( po, new FileOutputStream("modifiedpurchaseorder.xml"));

Much like the Unmarshaller, the Marshaller can marshal the Java object and its referenced objects (the content tree) into different destinations-files, DOM trees, and so on-summarized in Table 13.4.

Table 13.4: Marshalling Object Trees into Different Destinations

Marshalling method

Marshall the object and referenced objects therein into

public void marshall(Object obj, org.xml.sax.ContentHandler handler)

SAX2 events

public void marshall(Object obj, org.w3c.dom.Node node)

A DOM tree

public void marshall(Object obj, java.io.OutputStream os)

An output stream

public void marshall(Object obj, javax.xml.transform.Result result)

A javax.xml.transform.Result

Public void marshall(Object obj, java.io.Writer writer)

A Writer stream.

JAXB does not require that the Java content tree be valid or validated against the schema during the marshalling process to give the JAXB implementation the ability to support use cases where partial XML is generated. The provider may choose to disallow marshalling of invalid content and throw a MarshallException.

As with the Unmarshaller, event handlers can be registered with the Marshaller using the setEventHandler(ValidationEventHandler handler) method. Even though there is no way to programmatically enable validation during the marshall operation, it is possible for validation events to be received by the handler. The default handler will stop the marshalling when the first fatal error is encountered.

Configuring the Marshaller

The Marshaller can be configured using four standard properties, described in Table 13.5, that affect the XML formatting and output. The properties are passed as name-value pairs using the setProperty method, as shown below.

Table 13.5: Marshaller Properties

Property

Description

jaxb.encoding

The Marshaller will use "UTF-8" by default. If needed the encoding can be changed using this property.

jaxb.formatted.output

By default the Marshaller will not format the output with line breaks and indentations. If this property is set to true the XML generated will be formatted for human readability.

jaxb.schemaLocation

Used to set the xsi:schemaLocation attribute in the generated XML. (See Chapter 9 for details on this property.)

jaxb.noNamespaceSchemaLocation

Used to set the xsi:noNamespaceSchemaLocation property in the generated XML. (See Chapter 9 for details on this property.)

Marshaller mars = context.createMarshaller();
Mars.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
 mars.setProperty (Marshaller.JAXB_SCHEMA_LOCATION,
                         "http://www.flutebank.com/schema purchaseorder.xsd");

The Element Interface

JAXB defines the javax.xml.bind.Element interface used by the runtime as a marker for identifying the JAXB-generated binding interfaces. It has no methods. In some situations, application developers would need to write code implementing this interface. JAXB users always work with the generated Java binding interface and its methods, which encapsulate the name and value of the corresponding XML element. For example, the billingaddress element is mapped to the Billingaddress interface, which has methods to get/set the relevant types, which themselves are generated bindings. This was shown in Listing 13.2.

In XML schemas, the xsd:any element can be used to refer to elements not specified in the schema. For example, in the following fragment, the occupation element can be extended to include other content with the any element:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault=
                                                                          "qualified">
    <xsd:element name="occupation">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Engineer" type="xsd:string"/>
                <xsd:element name="SeniorEngineer" type="xsd:string"/>
                <xsd:element name="TechnicalWriter" type="xsd:string"/>

<xsd:any minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

This schema results in the generated binding shown below, which must cater to the potential of arbitary XML elements being specified whose name or value is not known at compile time.

public interface OccupationType {
    String getEngineer();
    void setEngineer(String value);
    javax.xml.bind.Element getAny();
    void setAny(javax.xml.bind.Element value);
    String getTechnicalWriter();
    void setTechnicalWriter(String value);
    String getSeniorEngineer();
    void setSeniorEngineer(String value);
}

When using this interface in application code, the code is responsible for passing an instance that implements the javax.bind.xml.Element interface, as opposed to the procedure with other Java data types.


Previous Section Next Section


JavaScript Editor Java Tutorials Free JavaScript Editor