kevin krouse xmlbeans committer nov. 17, 2004 copyright 2004 bea systems. licensed under the apache...
TRANSCRIPT
Kevin Krouse
XMLBeans Committer
Nov. 17, 2004
Copyright 2004 BEA Systems. Licensed under the Apache License, Version 2.0
Apache XMLBeans 2:Accessing the Full Power of XML in Java
Agenda
XmlBeans Overview
What’s new in Version 2
What’s under development for Version 2
What’s in the future for XmlBeans
XMLBeans Overview
Take Advantage of the full power of XML in Java
Underlying XML Store allows full access to the entire XML infoset whenever needed
Generated Java Classes allow Java-friendly access to XML
100% XML Schema Support
100% XML Infoset Access
Open technology (Apache Open Source)
Target
Enterprise Standard XML Technology
Make XMLSchema easy to use
Generated Java Classes
XML APIs
XML Store
XMLBeans Quick History and Status
Originally written by BEA for use within BEA technologies and for Weblogic Platform users (Weblogic Platform 8.1)
Submitted to Apache Open Source in Sep 2003 Became a top-level project in June 2004
Continued support and commitment from BEA 6 BEA Apache committers (of 13 total committers)
Released version 1.0.3 in June 2004
A Beta release of XMLBeans Version 2 very soon
XMLBeans Runtime
XML StoreHigh Speed Parser
pars
e
load
XMLBeans Architecture
XML APIs
Validation
Reads/Updates
XML Document Instance
XML Schema
Your XMLBeans Jar
Generated ClassesGenerated
ClassesGenerated
Interfaces/Classes
exte
nd
s
XML Schema Binaries(.xsb)
XML Schema Binaries(.xsb)
XML Schema Binaries(.xsb)
schema
compile
XmlObject XmlCursor DOM
(v2)
XPath STaX XQuery
XMLBeans Compile Time
Built-in schema types
codegen
schema type system (schema object model)
schema binaries (.xsb)compiled
interfaces/classes
schema validationXML
Schema
javac
GeneratedJava
Source
Schema Compilation
XmlTypes.jar
XMLBeans Generated Classes (1)
Schema’s targetNamespace becomes package name
Global elements and types become top-level classes
Anonymous types become inner classes
Local elements and attributes become properties
Simple type properties have both Java and XML set/get
<xs:schema targetNamespace="http://openuri.org/easypo"
xmlns:po="http://openuri.org/easypo"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="purchase-order">
<xs:complexType>
<xs:sequence>
<xs:element name="customer" type="po:customer"/>
<xs:element name="when" type="xs:dateTime"/>
<xs:element name="line-item" type="po:line-item"
minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="shipper" type="po:shipper" />
</xs:sequence>
</xs:complexType>
</xs:element>
XMLBeans Generated Classes (2)
First, the global element(s), and local elements …
Java Package: org.openuri.easypo
interface PurchaseOrderDocument extends XmlObject
interface PurchaseOrder extends XmlObject
Customer getCustomer()setCustomer(Customer)
Calendar getWhen()setWhen(Calendar)
LineItem[] getLineItemArray()addNewLineItem(LineItem)
Shipper getShipper()setShipper(Shipper)
synthetic type
XMLBeans Generated Classes (3)
<xs:complexType name="line-item">
<xs:sequence>
<xs:element name="description" type="xs:string"/>
<xs:element name="per-unit-ounces" type="xs:decimal"/>
<xs:element name="price" type="xs:double"/>
<xs:element name="quantity" type="xs:int"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="shipper">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="per-ounce-rate" type="xs:decimal"/>
</xs:sequence>
</xs:complexType><xs:complexType name="customer"> <xs:sequence> <xs:element name="name" type="xs:string"/> <xs:element name="phone"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:pattern value="\d\d\d-\d\d\d\d"/> </xs:restriction> </xs:simpleType> </xs:element> </xs:sequence></xs:complexType>
Next, we have the ‘named’ types:
interface CustomerString getName()setName(String)
String getPhone()setPhone (String)
Phone xgetPhone()xsetPhone(Phone)
interface ShipperString getName()setName(String)
BigDecimal getPerUnitOunces()setPerUnitOunces (BigDecimal)
interface LineItemString getDescription()setDescription(String)
BigDecimal getPerUnitOunces()setPerUnitOunces (BigDecimal)
double getPrice()setPrice(double)
int getQuantity()setQuantity(int)
interface Phone
XMLBeans Generated methods
Multiple Occurrence Methods:
LineItem[] getLineItemArray()void setLineItemArray(LineItem[] MyLineItems)
Array getter, setter
Get, set, insert, remove specific itemLineItem getLineItemArray(int index)void setLineItemArray(LineItem newLineItem, int index)void insertLineItem(int index, LineItem newLineItem)void removeLineItem(int index)
maxOccurs > 0
If simple type, then “x” version methods also gennedXmlString[] xgetPhoneArray()void xsetPhoneArray(XmlString[] phonesArray)XmlString xgetPhoneArray(int index)void xsetPhoneArray(int index, XmlString newPhone)XmlString insertNewPhone(int index)void addNewPhone(XmlString newPhone)
Adding new item to endvoid addLineItem(LineItem newLineItem)
Is item nil?boolean isNilLineItemArray(int index)void setNilLineItemArray(int index)
XMLBeans Type Hierarchy
XMLBeans Java Types hierarchy match XML Schema types
Built-in Types as well as User Defined Types derive from XmlObject.Just like java.lang.Object
Built-in Types are mapped to both Xml Type oriented classes and natural java classes
Xml Type oriented classes respect XML Schema rules (e.g., cannot assign negative integer to XmlPositiveInteger)
Valid assignments to corresponding java classes can be verified using validate()
A different way to work with XML A location in an XML Instance not a Node
Lighter weight than Node based model
Fewer Objects = Less Memory, Less Garbage Collection
Access to full XML infoset (comments, PIs, whitespace)
Programming model is different than many are used to
Think of moving a cursor through a text document <PurchaseOrder><Customer>Dave</Customer></PurchaseOrder>
XmlCursor’s programming model is token based (similar to StAX)
You can work at the character level if needed.
XmlCursor, the whys and wherefores
<?xml version=“1.0” encoding=“UTF-8” ?><!-- Order summary --><?xml-stylesheet type=“text/xsl” href=“order.xslt”?><WidgetOrder batchId=“3DJ” xmlns=“org.shipping”> <Order id=“12”> <item><name>Some Widget</name></item> </Order></WidgetOrder>
Understanding XML Tokens
9 Token Types• STARTDOC• ENDDOC• START• END• TEXT• ATTR• NAMESPACE• COMMENT• PROCINST
XMLStore Architecture
XML Instance
File
Stream
String
Etc.
XML Store
Tree
Character Buffer
<purchaseOrder>
<customer>
Etc.<lastName>
Parser
Load
XmlObject XmlCursor
XML Instance
File
Stream
String
Etc.
Save
User Code
myCursor.toFirstChild();myCursor.toChild(0);myCursor.toNextToken()myCursor.toParent();myCursor.toStartDoc();myCursor.toNextSibling();myCursor.toNextChar();myCursor.toNextAttribute();myCursor.toLastAttribute();
Using XmlCursor to navigate/read
Create an XmlCursor by calling newCursor method on XmlObjectXmlCursor myCursor = XmlObject.Factory.Parse(myXmlFile).newCursor();
There are many methods for moving around the XML
instance using XmlCursor
<xq:employees xmlns:xq="http://openuri.org/selectPath">
<xq:employee>
<xq:name>Fred Jones</xq:name>
<xq:address location="home">
<xq:street>900 Aurora Ave.</xq:street>
<xq:city>Seattle</xq:city>
<xq:state>WA</xq:state>
<xq:zip>98115</xq:zip>
</xq:address>
<xq:address location="work">
<xq:street>2011 152nd Avenue NE</xq:street>
<xq:city>Redmond</xq:city>
<xq:state>WA</xq:state>
<xq:zip>98052</xq:zip>
</xq:address>
<xq:phone location="work">(425)555-5665</xq:phone>
<xq:phone location="home">(206)555-5555</xq:phone>
<xq:phone location="mobile">(206)555-4321</xq:phone>
</xq:employee>
</xq:employees>
Using XmlCursor to add an element
XmlObject newXml = XmlObject.Factory.newInstance();
First, create empty document
Create cursor and bump past the STARTDOC tokenXmlCursor cursor = newXml.newCursor();cursor.toNextToken();
Create new element using beginElement()
cursor.beginElement("item", "http://openuri.org/");
Insert an “id” attribute with a value
cursor.insertAttributeWithValue("id", "4056404");
Insert “bicycle” as an element valuecursor.insertChars("bicycle");
<ns1:item id="4056404" xmlns:ns1="http://openuri.org/">bicycle</ns1:item>
Using XPath from XmlCursor
xmlCursor.selectPath(myXPathExpression)<xq:employees xmlns:xq="http://openuri.org/selectPath">
<xq:employee>
<xq:name>Fred Jones</xq:name>
<xq:address location="home">
<xq:street>900 Aurora Ave.</xq:street>
<xq:city>Seattle</xq:city>
<xq:state>WA</xq:state>
<xq:zip>98115</xq:zip>
</xq:address>
<xq:address location="work">
<xq:street>2011 152nd Avenue NE</xq:street>
<xq:city>Redmond</xq:city>
<xq:state>WA</xq:state>
<xq:zip>98052</xq:zip>
</xq:address>
<xq:phone location="work">(425)555-5665</xq:phone>
<xq:phone location="home">(206)555-5555</xq:phone>
<xq:phone location="mobile">(206)555-4321</xq:phone>
</xq:employee>
</xq:employees>
Iterate thru selections using xmlCursor.toNextSelection()
String queryExpression =
"declare namespace xq='http://openuri.org/selectPath'" +
"$this/xq:employees/xq:employee/xq:phone”
xmlCursor.selectPath(queryExpression)
For example:
while (xmlCursor.toNextSelection())
{
System.out.println(cursor.getTextValue());
}
Code to loop through selections:
(425)555-5665
1
1
2
(206)555-55552
3
(206)555-43213
public void tryPushPop(XmlObject xml)
{
XmlCursor cursor = xml.newCursor();
cursor.toFirstChild();
cursor.push();
cursor.toChild(2);
cursor.toNextSibling();
cursor.pop();
}
Using Stored Cursor Locations with push() and pop()
|<employee>
<name>Gladys Kravitz</name>
<address location="home">
<street>1313 Mockingbird Lane</street>
<city>Seattle</city>
<state>WA</state>
<zip>98115</zip>
</address>
<address location="work">
<street>2011 152nd Avenue NE</street>
<city>Redmond</city>
<state>WA</state>
<zip>98052</zip>
</address>
<phone location="work">(425) 555-6897</phone>
<phone location="home">(206) 555-6594</phone>
<phone location="mobile">(206) 555-7894</phone>
</employee>
Agenda
XmlBeans Overview
What’s new in Version 2
What’s under development for Version 2
What’s in the future for XmlBeans
New in XMLBeans Version 2
Extensions to generated code: Interface extensions
Pre/Post events for setters
New, improved XML store Perf enhancements, synchronization on/off modes
Native live DOM – modifications are in sync with XmlCursor, XmlObject
Error Codes New, improved Compiler API
Incremental compilation
New tools: inst2xsd and xsd2inst Binary metadata partitioning Many bug fixes and improvements…
Interface Extensions in Generated Code
“Can I extend a generated XMLBean class to add methods?” Don’t do it! You’ll be sorry!
How can I add methods to a generated XMLBean? The XMLBeans schema compiler can be configured to gen code
that implements a user provided interface.
The generated XMLBean interfaces and *Impl classes will implement the interface
The implementation will call static methods on a user provided handler class.
Interface Extensions: Example
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config"> <xb:extension for=“generated.PurchaseOrder generated.Shipper"> <xb:interface name=“com.example.FooInterface"> <xb:staticHandler>com.example.FooHandler</xb:staticHandler> </xb:interface> </xb:extension></xb:config>
Create an .xsdconfig file Name the generated classes theextension applies to
Provide an interface
public interface FooInterface{ String doMagic(int i);}
Provide a static implementation
public class FooHandler { public static String doMagic(XmlObject o, int i) { … }}
Interface Extensions: Example Cont.
public interface PurchaseOrder extends XmlObject, FooInterface{ …}
Generated PurchaseOrder interface implements FooInterface:
public interface FooInterface { String doMagic(int i);}
public class PurchaseOrderImpl extends XmlComplexContentImpl implements PurchaseOrder{ public String doMagic(int i) { return FooHandler.doMagic(this, i); } ...}
Generated PurchaseOrderImpl implements FooInterfaceby delegating to the FooHandler static methods
public class FooHandler { public static String doMagic(XmlObject o, int i) { … }}
Pre/Post Events for Setters
“Can I extend a generated XMLBean class and override methods?” Don’t do it! You’ll be sorry!
How can I override methods of a generated XMLBean? You can’t override, but…
The XMLBeans schema compiler can be configured to gen code that calls a preSet() and postSet() handler.
Pre/Post events are only for the .setXxx(), .insertXxx(), and .removeXxx() methods.
Pre/Post Events: Example
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config"> <xb:extension for=“generated.PurchaseOrder generated.Shipper"> <xb:prePostSet> <xb:staticHandler>com.example.SetterHandler</xb:staticHandler> </xb:prePostSet> </xb:extension>
Create an .xsdconfig file Name the generated classes theextension applies to
public class SetterHandler{ public static boolean preSet(int opType, XmlObject xo, QName prop, boolean isAttr, int index)
public static void postSet(int opType, XmlObject xo QName prop, boolean isAttr, int index)}
Handler class with preSet/postSet methodsopType is SET, INSERT, or REMOVE
XmlObject parameter is ‘this’
QName of the property being set
isAttr is true for attribute properties
The array index of the element or -1
preSet returns true, set continues
Pre/Post Events: Example Cont.
public class PurchaseOrderImpl extends XmlComplexContentImpl { private static final QName NAME$0 = new QName(“”, “name”);
public void setName(generated.NameType name) { if (com.example.SetterHandler.preSet(PrePostExtension.SET, this, NAME$0, false, -1))) { /* XmlBeans code to set the ‘name’ element */ } com.example.SetterHandler.postSet(PrePostExtension.SET, this, NAME$0, false, -1); }
Generated PurchaseOrderImpl calls pre/post handlers
public class SetterHandler {
public static boolean preSet(int opType, XmlObject xo, QName prop, boolean isAttr, int index) { return false; }
public static void postSet(int opType, XmlObject xo, QName prop, boolean isAttr, int index) { /* do nothing */ }
Handler below will make a ‘read-only’ XmlBean
New, improved XML Store
Performance in the store very important to us. Entire XML infoset loaded in store with a binding on top requires overhead
versus shredding the xml to stuff into a POJO
Performance improvements in v2 Fewer objects (interior elements took 2 objects in v1, take one object in v2)
Less char copying and less wasted char buffer space
Preserve user’s String values for attributes/elements
Optional thread safety – turn synchronization off
Simpler architecture – v1 used a splay tree
Native DOM level 2 implementation inside the store. Now you have three views of the underlying xml: XmlObject (strongly typed schema access)
XmlCursor (cursor/token model)
DOM level 2 (tree model)
Move between all three views seamlessly
New, improved Compiler API
Refactoring to make calling the schema compiler easier XmlBeans.compileXmlBeans(…)
Parses the XMLSchema input files, compiles into a SchemaTypeSystem, generates the XmlBeans binding java code
Caller still needs to run javac on the generated files
Incremental compilation Pass in the previously compiled SchemaTypeSystem
Interpreted as a diff against list of input schemas
Every namespace from previous compilation not found in current compilation is considered unchanged – moved to the new SchemaTypeSystem
Modified components are added to new STS
Error Codes
Programmatically get error codes from compilation, parsing, or validation.
Conforms to the XMLSchema spec, Appendix C error codes Error codes like “cvc-complex-type.2.2” are interpreted as
http://www.w3c.org/TR/xmlschema-1/#cvc-complex-type clause 2.2
Some fudge factor involved, not all errors have a clause or more than one error is possible in a clause.
Most all error/warning messages have been internationalized
List list = new ArrayList();XmlOptions opts = new XmlOptions().setErrorListener(list);XmlObject xobj = XmlObject.Factory.parse(myfile, opts);if (list.size() > 0) { XmlError err = ((XmlError)list.get(0); System.out.println(“err: “ +err.getErrorCode() + “: “ + err.getMessage());}
inst2xsd tool
Creating an new XMLSchema can be a burden.
If you have a handful of XML instances, you can create an XMLSchema from them using the instance 2 schema tool
Supports three schema design patterns: Russian-Doll (local elements and local types)
Salami Slice (element refs to global elements)
Venetian Blind (local elements and global complex types)
Supports the most narrow type applicable (ints, dates, etc)
Supports enumerations for repeated values
xsd2inst tool
Given a schema and a global element, xsd2inst will generate a sample xml document
The instance will contain values for simple types
Not all possible content models will be produced
Good for a interactive editing and testing of schema and web services
Binary Metadata partitioning
Warning: advanced feature of XMLBeans
What if you have two versions of a compiled XmlBean jar on the same classpath?
Geronimo and Beehive both use XmlBeans for editing deployment descriptors
Meta-data will conflict if they are in the same namespace:
When loading metadata about the “namespace:application” element, the “/schema/element/namespace/application.xsb” resource is read from the classpath
Solution to protect against classpath conflicts?
Classloaders. But Geronimo will probably want to put XmlBeans and the compiled descriptor jar on the system classpath. It’s easier.
Add another “package” directory to the resource lookup:
/schema/org.apache.geronimo/element/namespace/application.xsb
/schema/org.apache.beehive/element/namespace/application.xsb
Lots of bug fixes
Lots of bug fixes and improvements Better wildcard support
XmlObject[] XmlObject.selectChildren(QNameSet)
PurchaseOrder.type.qnameSetForWildcardElements()
Validation optimization
xsd:annotation support is new
Redefines completely rewritten
Substitution Groups works but better support in progress
Agenda
XmlBeans Overview
What’s new in Version 2
What’s under development for Version 2
What’s in the future for XmlBeans
Current development for Version 2
XMLStore optimizations for fast XQuery execution
Binding improvements Use JDK1.5 enumerations and generics in generated code
Better support for Substitution Groups
More performance work
Agenda
XmlBeans Overview
What’s new in Version 2
What’s under development for Version 2
What’s in the future for XmlBeans
In the Future
Streaming XmlBeans with schema type information A cursor-like model with ability to do typed operations such as
“skip until next PurchaseOrder”
Solves XML store loading entire documents in-memory
Binding improvements: Collections instead of strongly typed arrays
Binding API so multiple bindings can be used for a type system
e.g., XmlBeans, JAX-RPC, SDO, JAXB2, lossy POJOs
Incremental compilation (at the type level) a schema type system that can be incrementally built
great for an IDE/schema editor
Questions/Comments
“When you need to use XML and XMLSchema in Java, XMLBeans is the best!”
-- Ted Leung, from ApacheCon 2004 XML talk (Nov., 16th)
Any questions?
Site: http://xmlbeans.apache.org/ Wiki: http://wiki.apache.org/xmlbeans Email lists:
Slides:
http://www.apache.org/~kkrouse/apachecon/ac2004_XmlBeans_v2.ppt