440 likes | 611 Views
JAXB. The Java Architecture for XML Binding Bibliography: - JAXB User’s Guide from Sun Microsystems - Java and XML Data Binding by McLaughlin. JAXB. Like SAX and DOM in that the application developer does not have to parse the XML
E N D
JAXB • The Java Architecture for XML Binding • Bibliography: - JAXB User’s Guide from Sun Microsystems - Java and XML Data Binding by McLaughlin
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
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
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)
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
The Binding Schema • JAXB requires that we use a DTD AND a “Binding Schema” • The Binding Schema is an XML document JAXB .java file(s) DTD Binding Schema javac javac .class files
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 …
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
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>
Book.dtd <!ELEMENT book (title,author, chapter)> <!ELEMENT title (#PCDATA)> <!ELEMENT author (#PCDATA)> <!ELEMENT chapter (#PCDATA)>
A minimal binding schema Book.xjc <xml-java-binding-schema> <element name = "book" type = "class" root = "true" /> </xml-java-binding-schema>
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>
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;
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(); } }
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(); } }
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 { }
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); }
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 = ""; }
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"); }
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))); }
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; } }
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; }
} 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; }
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(); }
public static Dispatcher newDispatcher() { Dispatcher d = new Dispatcher(); d.register("book", (Book.class)); d.freezeElementNameMap(); return d; } }
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]));
// 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); } }
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
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>
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>
<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>
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>
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>
<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>
<!-- 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>
<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>
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
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.*;
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 );
// 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());
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(); } } }
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