For example, for the complex type catalogType, shown in Listing 6-33, the value class CatalogType.java gets generated.. Listing 6-35 shows public class ObjectFactory { private final sta
Trang 1Binding Catalog Schema to Java Classes
In this section, you will bind the catalog schema shown in Listing 6-6 to its Java content classes
You’ll subsequently use the Java content classes to marshal and unmarshal the XML document
shown in Listing 6-7 You will run xjc from within Eclipse Therefore, configure xjc as an external
tool in Eclipse, similar to the JAXB 1.0 project configuration The only difference for the JAXB 2.0
project is that the xjc batch file Location field is set to the JAXB 2.0 xjc batch file You set the
envi-ronment variables JAVA_HOME and JAXB_HOME similar to JAXB 1.0 Set JAXB_HOME for Chapter6-JAXB2.0
to C:\Sun\jwsdp-2.0\jaxb To add the xjc configuration to the External Tools menu, select the
Common tab, and select the check box External Tools in the Display in Favorites menu area, as
shown in Figure 6-7
To run the xjc compiler on the example schema, catalog.xsd, select the catalog.xsd file in the
Package Explorer and then select Run ➤ External Tools ➤ XJC Schema-derived classes get generated in
the gen_source folder, as shown in Figure 6-12
Figure 6-12 Schema-derived Java content classes generated by xjc
Java classes and interfaces are generated in the package generated by default Fewer classes are
generated with JAXB 2.0 than with JAXB 1.0 For each xsd:complexType schema component, one
value class gets generated, instead of an interface and an implementation class For example, for the
complex type catalogType, shown in Listing 6-33, the value class CatalogType.java gets generated
Listing 6-33 The Complex 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>
Trang 2172 C H A P T E R 6 ■ O B J E C T B I N D I N G W I T H J A X B
The CatalogType.java class consists of getter and setter methods for each of the attributes of the catalogType complex type A getter method for the complex type journalType with the return type List<JournalType> also gets generated Listing 6-34 shows CatalogType.java
public class CatalogType {
protected List<JournalType> journal;
@XmlAttribute
protected String publisher;
@XmlAttribute
protected String section;
public List<JournalType> getJournal() {
Trang 3public void setSection(String value) {
this.section = value;
}
}
Similarly, the value class JournalType.java gets generated for the complex type journalType,
and the value class ArticleType.java gets generated for the complex type articleType An
ObjectFactory.java factory class gets generated, which consists of the create methods for each of
the complex type and element declarations in the example schema For example, the ObjectFactory
class method for the complex type catalogType is createCatalogType(), and its return type is
CatalogType The ObjectFactory class method for the element catalog is
createCatalog(CatalogType), and its return type is JAXBElement<CatalogType> Listing 6-35 shows
public class ObjectFactory {
private final static QName _Article_QNAME = new QName("", "article");
private final static QName _Journal_QNAME = new QName("", "journal");
private final static QName _Catalog_QNAME = new QName("", "catalog");
public ObjectFactory() {
}
public JournalType createJournalType() {
return new JournalType();
}
public ArticleType createArticleType() {
return new ArticleType();
}
public CatalogType createCatalogType() {
return new CatalogType();
}
@XmlElementDecl(namespace = "", name = "article")
public JAXBElement<ArticleType> createArticle(ArticleType value) {
return new JAXBElement<ArticleType>
(_Article_QNAME, ArticleType.class, null, value);
}
Trang 4174 C H A P T E R 6 ■ O B J E C T B I N D I N G W I T H J A X B
@XmlElementDecl(namespace = "", name = "journal")
public JAXBElement<JournalType> createJournal(JournalType value) {
return new JAXBElement<JournalType>
(_Journal_QNAME, JournalType.class, null, value);
}
@XmlElementDecl(namespace = "", name = "catalog")
public JAXBElement<CatalogType> createCatalog(CatalogType value) {
return new JAXBElement<CatalogType>
(_Catalog_QNAME, CatalogType.class, null, value);
}
}
Marshaling an XML Document
Marshaling an XML document means creating an XML document from a Java object representation
of the XML document In the use case example, the web services client has to marshal the XML ment shown in Listing 6-7 In this section, we will show how to marshal such a document from a Java object tree that contains objects that are instances of schema-derived classes, generated with JAXB 2.0
docu-To marshal the example document, you need to follow these steps:
• Create a JAXBContext object, and use this object to create a Marshaller object
• Create an ObjectFactory object to create instances of the relevant generated Java content classes
• Using the ObjectFactory object, create an object tree with CatalogType as the root object Populate these tree objects with the relevant data using the appropriate setter methods
• Create a JAXBElement<CatalogType> object from the CatalogType object
JAXBElement<CatalogType> represents the catalog element in XML document
An application creates a new instance of the JAXBContext class with the static method
newInstance(String contextPath), where contextPath specifies a list of Java packages for the schema-derived classes In this case, generated contains the schema-derived classes, and you create this object as follows:
ObjectFactory factory=new ObjectFactory();
For each schema-derived Java class, a static factory method to create an object of that class
is defined in the ObjectFactory class The Java value class corresponding to the root element catalog complex type catalogType is CatalogType; therefore, create a CatalogType object with the createCatalogType() method of the ObjectFactory class:
CatalogType catalog = factory.createCatalogType();
Trang 5The root element in the XML document to be marshaled has the attributes section and publisher
The CatalogType value class provides the setter methods setSection() and setPublisher() for these
attributes You can set the section and publisher attributes with these setter methods, as shown in
Listing 6-36
Listing 6-36 Setting the section and publisher Attributes
catalog.setSection("Java Technology");
catalog.setPublisher("IBM developerWorks");
The Java value class for the journalType complex type is JournalType You create a JournalType
object with createJournalType(), as shown here:
JournalType journal = factory.createJournalType();
To add a JournalType object to a CatalogType object, obtain a parameterized type
List<JournalType> object for a CatalogType object and add the JournalType object to this List,
as shown in Listing 6-37
Listing 6-37 Adding a journal Element to the catalog Element
List<JournalType> journalList = catalog.getJournal();
journalList.add(journal);
The Java value object for the complex type articleType is ArticleType You create an ArticleType
object with the createArticleType() method of the ObjectFactory class:
ArticleType article = factory.createArticleType();
The element article has the attributes level and date for which the corresponding setter
methods in the ArticleType value object are setLevel() and setDate() You can set the attributes
level and date for an article element with these setter methods, as illustrated in Listing 6-38
Listing 6-38 Setting the Attributes level and date
article.setLevel("Intermediate");
article.setDate("January-2004");
The element article has the subelements title and author The ArticleType value object has
setter methods, setTitle() and setAuthor(), for setting the title and author elements, as shown in
Listing 6-39
Listing 6-39 Setting the title and author Elements
article.setTitle("Service Oriented Architecture Frameworks");
article.setAuthor("Naveen Balani");
To add an ArticleType object to a JournalType object, obtain a parameterized type
List<ArticleType> object from a JournalType object, and add the ArticleType object to this List,
as shown in Listing 6-40
Listing 6-40 Adding an article Element to a journal Element
List<ArticleType> articleList = journal.getArticle();
articleList.add(article);
To marshal the Java object representation CatalogType to an XML document, you need to
create a JAXBElement object of type CatalogType with the createCatalog(CatalogType) method’s
Trang 6public class JAXBMarshaller {
public void generateXMLDocument() {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("generated");
Marshaller marshaller = jaxbContext.createMarshaller();
generated.ObjectFactory factory = new generated.ObjectFactory();
CatalogType catalog = factory.createCatalogType();
catalog.setSection("Java Technology");
catalog.setPublisher("IBM developerWorks");
JournalType journal = factory.createJournalType();
ArticleType article = factory.createArticleType();
Trang 7public static void main(String[] argv) {
JAXBMarshaller jaxbMarshaller = new JAXBMarshaller();
jaxbMarshaller.generateXMLDocument();
}
}
Unmarshaling an XML Document
Unmarshaling means creating a Java object tree from an XML document In the example use case,
the website receives an XML document containing catalog information, and it needs to unmarshal
this document before it can process the catalog information contained within the document In this
section, we’ll show first how to unmarshal the example XML document using the JAXB 2.0 API, and
subsequently we’ll show how to access various element and attribute values in the resulting Java
object tree
To unmarshal, follow these steps:
1. The example XML document, catalog.xml (Listing 6-7), is the starting point for unmarshaling
Therefore, import catalog.xml to the Chapter6-JAXB2.0 project in Eclipse by selecting File ➤ Import
2. Create a JAXBContext object, and use this object to create an UnMarshaller object
3. The Unmarshaller class converts an XML document to a JAXBElement object of type CatalogType
4. Create a CatalogType object from the JAXBElement object
As discussed earlier, create a JAXBContext object, which implements the JAXB binding
frame-work unmarshal() operation
You need an Unmarshaller object to unmarshal an XML document to a Java object Therefore,
create an Unmarshaller object with the createUnmarshaller() method of the JAXBContext class, as
shown here:
Unmarshaller unMarshaller=jaxbContext.createUnmarshaller();
Trang 8178 C H A P T E R 6 ■ O B J E C T B I N D I N G W I T H J A X B
JAXB 2.0 deprecates the setValidating() method to validate the XML document being shaled in favor of the setSchema(Schema schema) method, whereby you can set the schema that should be used for validation during unmarshaling
unmar-To create a Java object representation of an XML document, unmarshal the XML document to obtain a JAXBElement object of type CatalogType Subsequently, obtain a CatalogType object from the JAXBElement object with the getValue() method, as shown in Listing 6-42
Listing 6-42 Unmarshaling an XML Document
Listing 6-43 Outputting the section and publisher Attributes
System.out.println("Section: "+catalog.getSection());
System.out.println("Publisher: "+catalog.getPublisher());
You can obtain a List<JournalType> object of JournalType objects for a CatalogType object with the getJournal() method of the CatalogType value object:
List<JournalType> journalList = catalog.getJournal();
Iterate over the List to obtain the JournalType objects, which correspond to the journal element in the XML document, catalog.xml, as shown in Listing 6-44
Listing 6-44 Retrieving Journal Objects for a Catalog Object
for (int i = 0; i < journalList.size(); i++) {
JournalType journal = (JournalType) journalList.get(i);
}
You can obtain a List of ArticleType objects with the getArticle() method of the JournalType value object, as shown here:
List<ArticleType> articleList = journal.getArticle();
To obtain ArticleType objects in an ArticleType List, iterate over the List, and retrieve ArticleType objects, as shown in Listing 6-45
Listing 6-45 Retrieving Article Objects from a List
for (int j = 0; j < articleList.size(); j++) {
ArticleType article = (ArticleType)articleList.get(j);
}
Trang 9An article element has the attributes level and date and the subelements title and author
You can access the values for the article element attributes and subelements with getter methods
for these attributes and elements, as shown in Listing 6-46
Listing 6-46 Outputting article Element Attributes and Subelements
System.out.println("Article Date: "+article.getDate());
System.out.println("Level: "+article.getLevel());
System.out.println("Title: "+article.getTitle());
System.out.println("Author: "+article.getAuthor());
The complete program, JAXBUnMarshaller.java, shown in Listing 6-47, demonstrates how to
unmarshal the example XML document following the steps outlined earlier The unmarshaling
application has the method unMarshall(File), which takes a File object as input The input file
should be the document to be unmarshaled
public class JAXBUnMarshaller {
public void unMarshall(File xmlDocument) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance("generated");
Unmarshaller unMarshaller = jaxbContext.createUnmarshaller();
JAXBElement<CatalogType> catalogElement = (JAXBElement<CatalogType>)
unMarshaller.unmarshal(xmlDocument);
CatalogType catalog=catalogElement.getValue();
System.out.println("Section: " + catalog.getSection());
System.out.println("Publisher: " + catalog.getPublisher());
List<JournalType> journalList = catalog.getJournal();
for (int i = 0; i < journalList.size(); i++) {
JournalType journal = (JournalType) journalList.get(i);
List<ArticleType> articleList = journal.getArticle();
for (int j = 0; j < articleList.size(); j++) {
ArticleType article = (ArticleType)articleList.get(j);
System.out.println("Article Date: " + article.getDate());
System.out.println("Level: " + article.getLevel());
System.out.println("Title: " + article.getTitle());
System.out.println("Author: " + article.getAuthor());
Trang 10public static void main(String[] argv) {
File xmlDocument = new File("catalog.xml");
JAXBUnMarshaller jaxbUnmarshaller = new JAXBUnMarshaller();
jaxbUnmarshaller.unMarshall(xmlDocument);
}
}
The output from unmarshaling the example XML document is the same as for the JAXB 1.0 project
Binding Java Classes to XML Schema
JAXB 2.0 supports bidirectional mapping between the XML Schema content and Java classes So far, you have looked at binding the XML Schema content to Java classes In this section, you will generate XML Schema content from a Java class using the JAXB 2.0 binding annotations Therefore, you need
to define an annotated class: Catalog.java To this class, you will apply the schemagen tool to generate
a schema definition
In the Catalog.java class, import the javax.xml.bind.annotation package that includes the binding annotation types Define the root element with the @XmlRootElement annotation Create a complex type using the @XmlType annotation:
@XmlRootElement
@XmlType(name="", propOrder={"publisher", "edition", "title", "author"})
You specify the annotation element name as an empty string because the complex type is defined anonymously within an element You specify the element order using the propOrder anno-tation element In the Catalog class, define constructors for the class, and define the different JavaBean properties (publisher, edition, title, author) The root element catalog has an attribute journal Define the journal attribute using the @XmlAttribute annotation:
@XmlAttribute
public String journal;
You also need to define getter and setter methods for the different properties and the journal attribute Listing 6-48 shows the complete Catalog.java class
@XmlType(name = "", propOrder = { "publisher", "edition", "title", "author" })
public class Catalog {
private String publisher;
private String edition;
Trang 11private String title;
private String author;
public Catalog() {
}
public Catalog(String journal, String publisher, String edition,
String title, String author) {
public String journal;
private String getJournal() {
Trang 12Figure 6-13 SCHEMAGEN configuration
To generate the XML Schema from the annotated class Catalog.java, select Catalog.java in the Package Explorer, and run the SCHEMAGEN configuration An XML Schema gets generated from the annotated class, as shown in Figure 6-14
Trang 13Figure 6-14 XML Schema generated from the annotated class Catalog.java
Summary
JAXB 1.0 specifies XML Schema binding to Java representation JAXB 2.0 specifies a bidirectional
XML Schema to Java representation Both specifications provide a binding compiler for generating
schema-derived Java content classes and a runtime framework for the marshaling and unmarshaling of
XML documents
You can customize the XML Schema binding to Java types through external or inline binding
declarations The external binding declarations allow the schema definition and customizations to
be cleanly separated and offer the advantage of applying different customizations to the same schema
definition to satisfy different binding objectives However, external binding declarations rely on
XPath expressions to address binding nodes for customizations and are therefore relatively more
complex to specify than inline bindings, which are specified within the schema definition and thus
address binding nodes implicitly
JAXB 2.0 provides following advantages over JAXB 1.0:
• Support for all the schema constructs
• A relatively compact binding of a schema definition to Java content classes
• Bidirectional mapping between schema definition and Java types
We strongly recommend using JAXB 2.0, unless you explicitly need to stay with JAXB 1.0, such
as for backward compatibility
Trang 15■ ■ ■
C H A P T E R 7
Binding with XMLBeans
XMLBeans,1 just like JAXB, is an XML-to-Java binding and runtime framework You can use the
binding framework to bind an XML Schema to Java types; you can use the runtime framework to
unmarshal and marshal an XML document to and from its Java binding classes If you are wondering
why you are studying another XML-to-Java binding, the answer lies in the following reasons:
• XMLBeans provides full support for XML Schema binding to Java types across multiple versions
of the Java platform Even though JAXB 2.0 provides full support for XML Schema, it requires
J2SE 5.0; XMLBeans is the only XML-to-Java binding with full schema support that works with
J2SE 1.4.x, as well as with J2SE 5.0.
• XMLBeans predates JAXB, and perhaps because of that, it has found its way into many more
commercial products than JAXB, although, admittedly, if JAXB 2.0 is widely adopted, this may
not last into the future
• XMLBeans defines the XmlObject API for access to XML information content through
type-safe Java classes XMLBeans also defines the XmlCursor API that provides cursor-based access to
the XML InfoSet that underlies an XML document This means by using XMLBeans, you can
access and manipulate information content through type-safe Java classes, and you can do so
in a manner that is related to the low-level details within the document, such as the order of
elements or attributes
• XMLBeans defines the SchemaType API that provides a schema object model for metadata
contained within an XML Schema This is useful if you want to dynamically create an XML
document that conforms to a schema
In our opinion, JAXB should be the default choice for a binding framework, because it is part of
the Java Platform Standard Edition However, in certain situations, for reasons discussed previously
and summarized in Table 7-1, XMLBeans may be the more pragmatic choice
In this chapter, we will primarily focus on the XMLBeans binding and runtime frameworks We
will also discuss the XmlCursor API related to the XML InfoSet; however, the APIs related to the
schema object model are beyond the scope of this chapter, mainly because we want to keep the
focus on the binding framework and because the SchemaType API is not central to this focus
1 This is part of the Apache XML Project; you can find detailed information related to this project at
http://xmlbeans.apache.org/overview.html
Trang 16docu-In this chapter, we will first show how to use the binding compiler to bind an example schema
to its Java types and then show how to use these Java types to marshal and unmarshal an example XML document Listing 7-1 shows the example schema
Table 7-1 XMLBeans vs JAXB
Feature XMLBeans JAXB
Bidirectional
mapping
Does not support bidirectional mapping between the XML Schema and the Java class
JAXB 2.0 supports bidirectional mapping between the XML Schema and the Java class.XML Schema
XML document
navigation
XMLBeans supports XML document navigation with cursors
JAXB does not support cursors
interfaces extend org.apache.xmlbeans.XmlObject
The JAXB JavaBeans interfaces do not extend a root interface
a XQuery 1.0 is an XML-based query language (http://www.w3.org/TR/xquery/)
Trang 17<xs:element name="article">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="author" type="xs:string"/>
</xs:sequence>
<xs:attribute name="level" type="xs:string"/>
<xs:attribute name="date" type="xs:string"/>
<xs:attribute name="section" type="xs:string"/>
</xs:complexType>
</xs:element>
Listing 7-2 shows the example XML document we will marshal and unmarshal The structure
and content of the example XML document, of course, conforms to the example XML schema
Listing 7-2 catalog.xml
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<journal publisher="IBM developerWorks">
<article level="Intermediate" date="January-2004" section="Java Technology">
<title>Service Oriented Architecture Frameworks</title>
<author>Naveen Balani</author> </article>
<article level="Advanced" date="October-2003" section="Java Technology">
<title>Advance DAO Programming</title>
<author>Sean Sullivan</author> </article>
<article level="Advanced" date="May-2002" section="Java Technology">
<title>Best Practices in EJB Exception Handling</title>
<author>Srikanth Shenoy </author> </article>
</journal>
</catalog>
We will show how to compile the example schema with the binding compiler Subsequently, we
will show how to unmarshal and marshal the example XML document using the Java classes
gener-ated from the schema
Setting Up the Eclipse Project
Before you can set up your project, you need to download XMLBeans2 2.0 and extract it to an
instal-lation directory You also need to download the Saxon3 8.1.1 XSLT and the XQuery4 processor; you’ll
use the Saxon 8.1.1 API to query an XML document with the XmlCursor API XMLBeans requires at
least J2SE 1.4.x We are using J2SE 5.0 because we used it for JAXB 2.0, and we think it is convenient
to continue using it for XMLBeans You may choose to follow suit or use J2SE 1.4.x If you follow this
choice, download and install J2SE 5.0, in case you have not already done so
2 You can download the XMLBeans binary version from http://xmlbeans.apache.org/
3 You can download this from http://sourceforge.net/project/
showfiles.php?group_id=29872&package_id=21888
4 We’ll discuss XQuery in the “Querying XML Document with XQuery” section
Trang 18188 C H A P T E R 7 ■ B I N D I N G W I T H X M L B E A N S
To compile and run the code examples, you will need an Eclipse project Download the project Chapter7 from the Apress website (http://www.apress.com), and import it into your Eclipse work-space, as described in Chapter 1
You need some XMLBeans JAR files in your project’s Java build path; Figure 7-1 shows these JAR files The JAR files required for an XMLBeans application are xbean.jar, which consists of the XMLBeans API, and jsr173_api.jar, which implements JSR-173, Streaming API for XML.5 You also need to set the JRE system library to JRE 5.0,6 as shown in Figure 7-1
Figure 7-1 Chapter7 project Java build path
You will configure the binding compiler scomp to generate Java content classes in the gen_source folder; therefore, add the gen_source folder to the source path on the Source tab in the Java build path area, as shown in Figure 7-2
Figure 7-3 shows the Chapter7 project directory structure
5 JSR-173 defines the StAX API, which we covered in Chapter 2 Information about JSR 173 is available at http://www.jcp.org/en/jsr/detail?id=173
6 As noted, you may choose to use JRE 1.4.x.
Trang 19Figure 7-2 Source path for the Chapter7 project
Figure 7-3 Chapter7 project directory structure
Compiling an XML Schema
In this section, you will first bind the example schema (catalog.xsd, shown in Listing 7-1) to its
corresponding Java types Subsequently, you will marshal and unmarshal the example XML
docu-ment (catalog.xml, shown in Listing 7-2) As noted earlier, you will use the scomp binding compiler
to bind the example schema There is a choice of syntax for scomp use, as shown in Listing 7-3