JAXB - Carnegie Mellon University

Download Report

Transcript JAXB - Carnegie Mellon University

JAXB
• The Java Architecture for XML Binding
• Bibliography:
- JAXB User’s Guide from Sun
Microsystems
- Java and XML Data Binding by
McLaughlin
1
JAXB
• Like SAX and DOM in that the application
developer does not have to parse the XML
• Unlike SAX and DOM it is tied to a
particular document schema
• Fast like SAX
• In memory representation like DOM but
without all the general tree manipulation
facilities
2
JAXB
• An XML Document is an instance of a
schema
• A Java object is an instance of a class
• JAXB reads a schema and produces a class
• Previously, the only schema supported was
the Document Type Definition (DTD)
• Currently, the only schema supported is
XSDL
3
In general - Data Binding involves:
• Source generation
From constraints to code
• Unmarshalling
Reading
• Marshalling
Writing
• Binding Schemas
Details about how the XML is to be mapped to
Java classes (very important with DTD’s)
4
JAXB
• Augments the standard DTD by providing type
conversion
<!ELEMENT notional (#PCDATA)>
:
:
<notional>100.00</notional>
• With JAXB we can make sure that Java converts
this to a BigDecimal automatically
5
The Binding Schema
• JAXB requires that we use a DTD AND a
“Binding Schema”
• The Binding Schema is an XML document
.java file(s)
DTD
JAXB
Binding
Schema
javac
.class files
6
The Binding Schema
• The binding schema contains instructions on how
to bind a schema to classes.
• It might say that :
– this attribute (in the XML document) should be treated
as an int
– this element’s content is a BigDecimal
– this element’s content is a String
– this element should be treated as a class
– and so on …
7
Running Old JAXB with DTD’s
C:\McCarthy\www\95-733\examples\jaxb>java -jar
D:\jaxb\jaxb-1.0-ea\lib\jaxb-xjc-1.0-ea.jar -help
Usage: xjc <schema> [ <binding-schema> ] [ -d <directory> ]
[ -roots <element-list> ]
Options:
-d <directory>
Specify the destination directory for the
Java output
-roots <element-list> Designate one or more root elements
(comma separated)
-version
Print the compiler's version number and exit
-help
Print this message and exit
8
Book.xml
<?xml version="1.0" encoding="UTF-8"
standalone="no"?>
<!DOCTYPE book SYSTEM "book.dtd">
<book>
<title>The Catcher in the Rye </title>
<author>J.D. Salinger </author>
<chapter>If you really want to hear about it...
</chapter>
</book>
9
Book.dtd
<!ELEMENT book (title,author, chapter)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT chapter (#PCDATA)>
10
A minimal binding schema
Book.xjc
<xml-java-binding-schema>
<element name = "book" type = "class" root = "true" />
</xml-java-binding-schema>
11
Run old JAXB
C:\McCarthy\www\95-733\examples\jaxb>java -jar
D:\jaxb\jaxb-1.0-ea\lib\jaxb-xjc-1.0-ea.jar book0.dtd book.xjc
.\Book.java
C:\McCarthy\www\95-733\examples\jaxb>
12
Resulting Book.java file
import java.io.IOException;
import java.io.InputStream;
import javax.xml.bind.ConversionException;
import javax.xml.bind.Dispatcher;
import javax.xml.bind.InvalidAttributeException;
import javax.xml.bind.LocalValidationException;
import javax.xml.bind.MarshallableRootElement;
import javax.xml.bind.Marshaller;
import javax.xml.bind.MissingContentException;
import javax.xml.bind.RootElement;
import javax.xml.bind.StructureValidationException;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Validator;
import javax.xml.marshal.XMLScanner;
import javax.xml.marshal.XMLWriter;
13
public class Book
extends MarshallableRootElement
implements RootElement
{
private String _Title;
private String _Author;
private String _Chapter;
public String getTitle() {
return _Title;
}
public void setTitle(String _Title) {
this._Title = _Title;
if (_Title == null) {
invalidate();
}
}
14
public String getAuthor() {
return _Author;
}
public void setAuthor(String _Author) {
this._Author = _Author;
if (_Author == null) {
invalidate();
}
}
public String getChapter() {
return _Chapter;
}
public void setChapter(String _Chapter) {
this._Chapter = _Chapter;
if (_Chapter == null) {
invalidate();
}
}
15
public void validateThis()
throws LocalValidationException
{
if (_Title == null) {
throw new MissingContentException("title");
}
if (_Author == null) {
throw new MissingContentException("author");
}
if (_Chapter == null) {
throw new MissingContentException("chapter");
}
}
public void validate(Validator v)
throws StructureValidationException
{
}
16
public void marshal(Marshaller m)
throws IOException
{
XMLWriter w = m.writer();
w.start("book");
w.leaf("title", _Title.toString());
w.leaf("author", _Author.toString());
w.leaf("chapter", _Chapter.toString());
w.end("book");
}
public void unmarshal(Unmarshaller u)
throws UnmarshalException
{
XMLScanner xs = u.scanner();
Validator v = u.validator();
xs.takeStart("book");
while (xs.atAttribute()) {
String an = xs.takeAttributeName();
throw new InvalidAttributeException(an);
}
17
if (xs.atStart("title")) {
xs.takeStart("title");
String s;
if (xs.atChars(XMLScanner.WS_COLLAPSE)) {
s = xs.takeChars(XMLScanner.WS_COLLAPSE);
} else {
s = "";
}
try {
_Title = String.valueOf(s);
} catch (Exception x) {
throw new ConversionException("title", x);
}
xs.takeEnd("title");
}
if (xs.atStart("author")) {
xs.takeStart("author");
String s;
if (xs.atChars(XMLScanner.WS_COLLAPSE)) {
s = xs.takeChars(XMLScanner.WS_COLLAPSE);
} else {
s = "";
18
try {
_Author = String.valueOf(s);
} catch (Exception x) {
throw new ConversionException("author", x);
}
xs.takeEnd("author");
}
if (xs.atStart("chapter")) {
xs.takeStart("chapter");
String s;
if (xs.atChars(XMLScanner.WS_COLLAPSE)) {
s = xs.takeChars(XMLScanner.WS_COLLAPSE);
} else {
s = "";
}
try {
_Chapter = String.valueOf(s);
} catch (Exception x) {
throw new ConversionException("chapter", x);
}
xs.takeEnd("chapter");
19
xs.takeEnd("book");
}
public static Book unmarshal(InputStream in)
throws UnmarshalException
{
return unmarshal(XMLScanner.open(in));
}
public static Book unmarshal(XMLScanner xs)
throws UnmarshalException
{
return unmarshal(xs, newDispatcher());
}
public static Book unmarshal(XMLScanner xs, Dispatcher d)
throws UnmarshalException
{
return ((Book) d.unmarshal(xs, (Book.class)));
}
20
public boolean equals(Object ob) {
if (this == ob) {
return true;
}
if (!(ob instanceof Book)) {
return false;
}
Book tob = ((Book) ob);
if (_Title!= null) {
if (tob._Title == null) {
return false;
}
if (!_Title.equals(tob._Title)) {
return false;
}
} else {
if (tob._Title!= null) {
return false;
}
}
21
if (_Author!= null) {
if (tob._Author == null) {
return false;
}
if (!_Author.equals(tob._Author)) {
return false;
}
} else {
if (tob._Author!= null) {
return false;
}
}
if (_Chapter!= null) {
if (tob._Chapter == null) {
return false;
}
if (!_Chapter.equals(tob._Chapter)) {
return false;
}
22
} else {
if (tob._Chapter!= null) {
return false;
}
}
return true;
}
public int hashCode() {
int h = 0;
h = ((127 *h)+((_Title!= null)?_Title.hashCode(): 0));
h = ((127 *h)+((_Author!= null)?_Author.hashCode(): 0));
h = ((127 *h)+((_Chapter!= null)?_Chapter.hashCode(): 0));
return h;
}
23
public String toString() {
StringBuffer sb = new StringBuffer("<<book");
if (_Title!= null) {
sb.append(" title=");
sb.append(_Title.toString());
}
if (_Author!= null) {
sb.append(" author=");
sb.append(_Author.toString());
}
if (_Chapter!= null) {
sb.append(" chapter=");
sb.append(_Chapter.toString());
}
sb.append(">>");
return sb.toString();
}
24
public static Dispatcher newDispatcher() {
Dispatcher d = new Dispatcher();
d.register("book", (Book.class));
d.freezeElementNameMap();
return d;
}
}
25
A Driver Program
// demo JAXB
import java.io.*;
public class TestJaxb {
public static void main(String args[]) throws
java.io.FileNotFoundException,
javax.xml.bind.UnmarshalException,
java.io.IOException {
DataInputStream in =
new DataInputStream(
new BufferedInputStream(
new FileInputStream(args[0])));
DataOutputStream out =
new DataOutputStream(
new FileOutputStream(args[1]));
26
// read in the book
Book catcher = Book.unmarshal(in);
// change its title
catcher.setTitle("Gone With The Wind");
// write out the book
catcher.marshal(out);
}
}
27
Compile and Run
C:\McCarthy\www\95-733\examples\jaxb>javac Book.java
C:\McCarthy\www\95-733\examples\jaxb>javac TestJaxb.java
C:\McCarthy\www\95-733\examples\jaxb>java TestJaxb
book.xml out.xml
28
Out.xml
<?xml version="1.0" encoding="UTF-8"?>
<book>
<title>Gone With The Wind</title>
<author>J.D. Salinger</author>
<chapter>If you really want to hear about it...</chapter></book>
29
Using the new JAXB
30
An XSDL Document for an ItemList
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema
xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:element name="itemList">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="item"
minOccurs="0" maxOccurs="3"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
31
<xsd:element name="item">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="name"/>
<xsd:element ref="quantity"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="quantity" type="xsd:short"/>
</xsd:schema>
32
A Document Instance
<?xml version="1.0" encoding="utf-8"?>
<itemList
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation="itemList.xsd">
<item>
<name>pen</name>
<quantity>5</quantity>
</item>
<item>
<name>eraser</name>
<quantity>7</quantity>
</item>
<item>
<name>stapler</name>
<quantity>2</quantity>
</item>
</itemList>
33
An Ant Build file
<?xml version="1.0"?>
<!– adapted from Sun’s jaxb build file 
<project basedir="." default="run">
<path id="classpath">
<fileset dir="D:\jwsdp-1.2\jaxb\lib" includes="*.jar"/>
<fileset dir="D:\jwsdp-1.2\common\lib" includes="*.jar"/>
<fileset dir="D:\jwsdp-1.2\jaxp\lib\endorsed" includes="*.jar"/>
<fileset dir="D:\jwsdp-1.2\jwsdp-shared\lib" includes="*.jar"/>
<fileset dir="D:\jwsdp-1.2\jaxp\lib" includes="*.jar"/>
<pathelement location="."/>
</path>
34
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
<classpath refid="classpath" />
</taskdef>
<!-- generate Java source files -->
<target name="generate">
<!-- generate the Java content classes from the schema -->
<echo message="Compiling the schema..."/>
<xjc schema="itemList.xsd" target="." package="itemListAPI"/>
<!-- generate the javadocs from the content classes -->
<mkdir dir="docs/api"/>
<javadoc packagenames="itemListAPI"
sourcepath="."
destdir="docs/api"
windowtitle="Generated Interfaces for itemList.xsd">
<classpath refid="classpath" />
</javadoc>
35
<!-- compile all of the java sources -->
<echo message="Compiling the java source files..."/>
<javac srcdir="." destdir="." debug="on">
<classpath refid="classpath" />
</javac>
</target>
<target name="JustJava">
<!-- compile all of the java sources -->
<echo message="Compiling the java source files..."/>
<javac srcdir="." destdir="." debug="on">
<classpath refid="classpath" />
</javac>
</target>
36
<target name="JustJavaRun">
<echo message="java runtime"/>
<java classname="Main" fork="true">
<classpath refid="classpath" />
</java>
</target>
<target name="run" depends="generate">
<echo message="Running the sample application..."/>
<java classname="Main" fork="true">
<classpath refid="classpath" />
</java>
</target>
</project>
37
Running the build
D:\McCarthy\www\95-733\examples\struts1\src\VO>ant generate
Buildfile: build.xml
generate:
[echo] Compiling the schema...
[xjc] Compiling file:/D:/McCarthy/www/95-733/examples/struts1/src/VO/itemL
ist.xsd
[xjc] Writing output to D:\McCarthy\www\95-733\examples\struts1\src\VO
[javadoc] Generating Javadoc
[javadoc] Javadoc execution
[javadoc] Loading source files for package itemListAPI...
[javadoc] Constructing Javadoc information...
[javadoc] Standard Doclet version 1.4.2
[javadoc] Building tree for all the packages and classes...
[javadoc] Building index for all the packages and classes...
[javadoc] Building index for all classes...
[echo] Compiling the java source files...
[javac] Compiling 42 source files to D:\McCarthy\www\95-733\examples\struts1
\src\VO
BUILD SUCCESSFUL
38
Viewing the docs
39
Write the client
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.util.ValidationEventCollector;
// import java content classes generated by binding compiler
import itemListAPI.*;
40
public class Main {
// This sample application demonstrates how to enable validation during
// the unmarshal operations.
public static void main( String[] args ) {
try {
// create a JAXBContext capable of handling classes generated into
// the itemListAPI package
JAXBContext jc = JAXBContext.newInstance( "itemListAPI" );
// create an Unmarshaller
Unmarshaller u = jc.createUnmarshaller();
// enable validation
u.setValidating( true );
41
// in this example, we will allow the Unmarshaller's default
// ValidationEventHandler to receive notification of warnings
// and errors which will be sent to System.out. The default
// ValidationEventHandler will cause the unmarshal operation
// to fail with an UnmarshalException after encountering the
// first error or fatal error.
// unmarshal an invalid itemList instance document into a tree of Java
// content objects composed of classes from the itemListAPI package.
ItemList itemList =
(ItemList)u.unmarshal( new File( "itemList.xml" ) );
java.util.List list = itemList.getItem();
System.out.println("The length of the list is " + list.size());
42
int n = list.size();
for(int k = 0; k < n; k++) {
ItemType it = (ItemType)list.get(k);
String st = it.getName();
System.out.println(st);
}
} catch( UnmarshalException ue ) {
// The JAXB specification does not mandate how the JAXB provider
// must behave when attempting to unmarshal invalid XML data. In
// those cases, the JAXB provider is allowed to terminate the
// call to unmarshal with an UnmarshalException.
System.out.println( "Caught UnmarshalException" );
} catch( JAXBException je ) {
je.printStackTrace();
}
}
}
43
Running the Client
D:\McCarthy\www\95-733\examples\struts1\src\VO>ant JustJavaRun
Buildfile: build.xml
JustJavaRun:
[echo] java runtime
[java] The length of the list is 3
[java] pen
[java] eraser
[java] stapler
BUILD SUCCESSFUL
Total time: 2 seconds
44