XMLBeans 2.0 - A Java Developer's Perspective
Pages: 1, 2, 3, 4

Error Codes

Error codes are the next great feature provided in the 2.0 release. Methods have been created to integrate this new feature with tools like scomp as well as allow for programmatic access for use within, say, an IDE. Appendix C of the XML Schema specification defines a set of error codes defining improper schema articles. Error codes are made available programmatically during parsing, validation, and compilation—using the error listener. Previously, the detail and schema conformance of error messages was minimal at best. Additionally, detailed information about where the error is located and its correlation to the schema specification have been added. The error codes themselves are defined in the form "cvc-complex-type.2.2" and can be interpreted as http://www.w3c.org/TR/xmlschema-1/#cvc-complex-type clause 2.2. Let's take a look at how this works now. We'll start with an XML Schema and validate an instance against it. Then we'll look at the old errors and compare them to the latest ones we receive.

 1 <!-- errorcode.xsd -->
 2 <xs:schema
 3   xmlns:xs="http://www.w3.org/2001/XMLSchema"
 4   targetNamespace="http://xmlbeans.rocks.com/"
 5   xmlns:tns="http://xmlbeans.rocks.com/" >
 6   <xs:element name="address" type="tns:address"/>
 7   <xs:complexType name="address">
 8     <xs:sequence>
 9       <xs:element name="number" type="xs:unsignedInt"/>
10       <xs:element name="street" type="xs:string"/>
11       <xs:choice>
12         <xs:sequence>
13           <xs:element name="city" type="xs:string"/>
14           <xs:element name="state" type="xs:string"/>
15         </xs:sequence>
16         <xs:element name="zipcode" type="xs:int"/>
17       </xs:choice>
18       <xs:element name="country" type="xs:string"/>
19     </xs:sequence>
20   </xs:complexType>
21 </xs:schema>

This is a pretty simple schema. Note the use of the xs:choice model group as this is what the following instance will not define properly. You'll see the issue as soon as we start looking at some of the error codes:

 1 <!-- errorcode.xml -->
 2 <t:address 
 3   xmlns:t="http://xmlbeans.rocks.com/" >
 4   <number>72</number>
 5   <street>156th NE</street>
 6   <country>USA</country>
 7 </t:address>

Along with the scomp utility available from the command line, a utility exists to validate an instance against a schema:

Validates the specified instance against the specified schema.
Contrast with the svalidate tool, which validates using a stream.
Usage: validate [-dl] [-nopvr] [-noupa] [-license] 
                schema.xsd instance.xml
 -dl - permit network downloads for imports and
            includes (default is off)
 -noupa - do not enforce the unique particle attribution rule
 -nopvr - do not enforce the particle valid (restriction) rule
 -partial - allow partial schema type system
 -license - print license information

If we ran the validate utility using the 1.0 branch of XMLBeans, the result would look like this:

/home/user>validate errorcode.xsd errorcode.xml
        errorcode.xml:0: error: Expected elements 
        city zipcode at the end of the content in element

The error text above notes the name of the instance, and tells us we are missing some expected elements at the end of address. In this small example, this is somewhat helpful, but without a line number it is hard to find a starting point. Let's compare this error text to the new error code feature in the latest release:

 /home/user>validate errorcode.xsd errorcode.xml
 errorcode.xml:4: error: cvc-complex-type.2.4a: Expected elements
 'city state' instead of 'country' here in element
 errorcode.xml:4: error: cvc-complex-type.2.4c: Expected elements 
 'zipcode' before the end of the content in element

In comparison to the error text we received in the 1.0 release of XMLBeans, we can see that the latest error text is a major improvement. Both error texts note the instance, but the latest also mentions the line number, the severity of the issue, the appendix C schema reference, and a more distinct error message. Additionally, with the new error codes, we see that there are more issues for the failing conditions as noted by the error codes cvc-complex-type.2.4a and cvc-complex-type.2.4c. Once again, these error codes correspond to a URL-accessible location in the schema specification.

We just looked at how we could get detailed error text from the command line, now let's peek at how we can get the error information programmatically:

 1 // Create the error listener and XmlOptions 
 2 LinkedList list = new LinkedList();
 3 XmlOptions opts = new XmlOptions().setErrorListener(list);
 5 // Load the instance
 6 File instance = new File("<SOME_PATH>\errorcodes.xml");
 7 AddressDocument ad = AddressDocument.Factory.parse(instance); 
 9 // If there are errors, making a method call like this will 
10 // populate the error listener
11 ad.validate(opts); 
13 // Since we know there are errors, let's
14 // look at how to get at the data 
15 for(int i=0; i < errors.size(); i++) {
17   // Cast list object to an XmlError 
     // type XmlError e = (XmlError)
18   errors.get(i);
20   // Now, let's get at all the information about the error
21   // This will be the location of the error in the instance
22   System.out.println("["+e.getLine()+","+e.getColumn()+"]-" + 
23   // Information about the error
24   System.out.println(e.getErrorCode() + ": " +e.getMessage());
25 }

Looking at the code snippet, you can see that programmatically accessing the error information is not much more difficult than getting similar information from the command line.

Performance Improvements

There's a good chance you may never notice the previous feature, but the impact to your development effort will surely be noticed. What good is a new release if there aren't performance improvements along the way?

As in XMLBeans 1.0, performance was paramount to the 2.0 release. In most cases, performance updates in the 2.0 release created a 10- to 60-percent increase over the numbers seen in the 1.0 release. There were several reasons for this, most notably a complete rewrite of the store architecture. In 1.0, a data structure called a "splay tree " was used to keep everything in the XML Store in sync with operations that affected the XML data. For those unfamiliar with this, a splay tree is a balanced tree that supports operation Find, Insert, and Delete in O(log N) time. This kind of data structure is different from other such trees in that it doesn't maintain an explicit balance condition. That's probably more detail than you need to know for most purposes. In the 2.0 release, a simpler architecture was used that provides for less copying and fewer objects.

When performing any operations on XML data, XMLBeans loads an XML Store. XMLBeans always loads an XML Store and then provides a binding view on to the Store. When compared to other Java/XML binding frameworks that unmarshal directly to Java objects, this binding view and full XML Infoset fidelity typically is where the additional overhead comes from. This makes the performance bar all the higher for XMLBeans so that the tradeoff for additional functionality and information is minimal. The primary focus for runtime performance is in the area of the XML Store, and every effort is made to make the Store as performant as possible.

While the XML Store was being rewritten, a new feature was added that made programming with XMLBeans more performant and easier to use. This feature was DOM Level II support. DOM is short for Document Object Model, and it represents an interface for working with XML data. Level II just specifies which interfaces are available. It differs from SAX in that the XML information is kept in memory.

Native DOM II Support

In the 1.0 release, access to the DOM was handled by Xerces, so such calls returned a Xerces DOM Node. In 2.0, similar calls return an XMLBeans DOM representation as DOM II is now implemented natively. This means that inside XMLBeans you can access a DOM representation and an XMLBeans representation without having to coordinate two different data stores.

This also means you can work with XML in any one of three ways. The first way is to use JavaBean-like methods in the XmlObject API. The second is to use the token-based model via the XMLCursor API. And the third way is to use the tree model familiar to all those who know the DOM APIs. What is particularly nice about this is that you can move back and forth between these methods and not have to worry about the instance being out of sync. From a developer perspective, this means you or your other team members can work with XML in the way they work best. Let's take a brief look at some of the APIs you can move between for these underlying views of the XML:

//To get the live DOM Node:
Node  XmlObject.getDomNode()
Node  XmlCursor.getDomNode()

//To get back:
XmlObject XmlBeans.nodeToObject(Node n)
XmlCursor XmlBeans.nodeToCursor(Node n)

//XMLBeans 1.0 API returns a copy:
Node XmlObject.newDomNode()

As you can see from the code above, moving between these views is tremendously easy.


This article provided a look at some of the new features available in XMLBeans 2.0. Along the way we learned that XMLBeans offers a robust, full-fidelity Java-to-XML binding framework. We also saw how using some of the new features of XMLBeans 2.0 made one of our projects much faster and easier. These new features increase our productivity as developers. The performance improvements also help our productivity, but mostly these improvements mean you will spend less time debugging and profiling bottlenecks in your applications.

The features we described are only some of the improvements in the latest release of XMLBeans. Please take a look at XMLBeans and see how you may be able to use it to increase your own development efforts.

Additional Reading

Jacob Danner is a Senior Software Engineer at BEA. He has been with BEA on the WebLogic Workshop team since its inception in 2001.

Raj Alagumalai is a Senior Developer Relations Engineer at BEA Systems in the WebLogic Workshop support division.