Download presentation
Presentation is loading. Please wait.
Published byRandell Daniels Modified over 10 years ago
1
Java-XML binding approaches @ Apache © 2005 Thomas Dudziak tomdz@apache.org
2
What’s in it Binding approaches Short detour: XML Schema The sample schema & data The tools JAXB, JaxMe, XMLBeans XStream JiBX, commons-betwixt A few notes about performance How to choose the right approach
3
Binding ? Java apps deal with data in XML But SAX/DOM is tedious Java XML binding to the rescue It handles converting between Java objects and XML entities for you It‘s not that easy, of course …
4
What we have and what we want Several binding approaches are available Document vs. model centric Which one is good depends on what you start with: XML, possibly even with a fixed Schema Java model classes Functional and technical constraints Worst case: fixed XML schema and fixed Java classes
5
Binding approaches Document centric Schema Java compilers Extension of the Java language Model centric XML Serialization Java Schema compilers Mixed Java – XML Mapping
6
The presented tools Java Schema compilers JAXB RI & JAXB 2 RI JaxMe 2 XMLBeans XML Serialization XStream Mapping JiBX Commons-betwixt
7
Detour: XML Schema (I) W3C standard, http://www.w3.org/XML/Schema http://www.w3.org/XML/Schema ‘extends’ DTD by providing significantly enhanced possibilities to constrain the content of attributes and elements Object-oriented approach with types and inheritance But …
8
Detour: XML Schema (II) "Over time, many people have complained to the W3C about the complexity of DTDs and have asked for something simpler. W3C listened, assigned a committee to work on the problem, and came up with a solution that is much more complex than DTDs ever were“ (Steven Holzner, "Inside XML", p.199)
9
The sample data <gui:panel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.apachecon.com/talks/java-xml-binding" xmlns:gui="http://www.apachecon.com/talks/java-xml-binding" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.apachecon.com/talks/java-xml-binding file:gui.xsd"> Some text Some other text
10
The sample schema (I)
11
The sample schema (II) <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink" targetNamespace="http://www.apachecon.com/talks/java-xml-binding" xmlns:gui="http://www.apachecon.com/talks/java-xml-binding" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>
12
The sample schema (III) <xsd:attribute name="alignment" type="gui:label-alignment-type" default="left"/>
13
The sample schema (IV) <xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
14
Schema Java compilers (I) It generates Java classes (beans) from the XML structure defined by a schema Usually one Java class per (complex) type Also performs datatype conversion JSR-31, JAXB or "Java Architecture for XML Binding", defines a standard Presented tools: JAXB Reference Implementation, JaxMe, XMLBeans Other known tools: Castor (http://www.castor.org), JBind (http://jbind.sourceforge.net/jBind.html)http://www.castor.org
15
Schema Java compilers (II) Benefits: Generated code is usually fast Code is strongly typed Classes directly correspond to the Schema – makes it easy to work with complex XML Problems: Requires an expressive Schema Schema is the final authority Generated code supports only one version of the Schema Is best suited when working with a fixed Schema (version)
16
JAXB (I) "Java Architecture for XML Binding" JSR-31, JSR-222 (final review phase) Special interest in the integration with web service technology, esp. JAX-WS Defines a standard binding scheme: Specification for generating Java interfaces and classes that correspond to XML Schema elements Standard API and infrastructure in the java.xml.bind package Basic customization options JAXB 2: annotations describing the binding
17
JAXB (II)
18
JAXB (III) Benefits (JAXB-specific) Standard that will be (is) part of Java 6 Validation can be performed any time Annotations may combine benefits of Schema Java compilers & mapping Problems (JAXB-specific) XML Schema not fully supported Generated classes are complicated JAXB 2 is not fully backwards compatible
19
JAXB 1 & 2 RI http://jaxb.dev.java.net/ http://jaxb.dev.java.net/ Reference implementations for the JSRs as required by the JCP JAXB 1 is open source under the CDDL JAXB 2 is currently Early Access and has a quite limited license (evaluation only)
20
JAXB RI: Generated code (I) public interface LabelType { java.lang.String getValue(); void setValue(java.lang.String value); java.lang.String getAlignment(); void setAlignment(java.lang.String value); } public interface PanelType { java.util.List getAny(); java.util.List getButtonOrLabelOrPanel(); public interface Button extends javax.xml.bind.Element, test.jaxb.ButtonType {} public interface Label extends javax.xml.bind.Element, test.jaxb.LabelType {} public interface Panel extends javax.xml.bind.Element, test.jaxb.PanelType {} }
21
JAXB RI: Generated code (II) public class ObjectFactory extends test.jaxb.impl.runtime.DefaultJAXBContextImpl { public test.jaxb.Panel createPanel() throws javax.xml.bind.JAXBException { return new test.jaxb.impl.PanelImpl(); } public test.jaxb.PanelType createPanelType() throws javax.xml.bind.JAXBException { return new test.jaxb.impl.PanelTypeImpl(); } public test.jaxb.PanelType.Label createPanelTypeLabel() throws javax.xml.bind.JAXBException { return new test.jaxb.impl.PanelTypeImpl.LabelImpl(); } public test.jaxb.PanelType.Panel createPanelTypePanel() throws javax.xml.bind.JAXBException { return new test.jaxb.impl.PanelTypeImpl.PanelImpl(); }... }
22
JAXB RI: Using it (I) JAXBContext context = JAXBContext.newInstance("test.jaxb"); // read from a file Unmarshaller unmarshaller = context.createUnmarshaller(); PanelType panel = (PanelType)unmarshaller.unmarshal(inputFile); for (Iterator it = panel.getButtonOrLabelOrPanel().iterator(); it.hasNext();) { ModelBase modelObj = (ModelBase)it.next(); if (modelObj instanceof ButtonType) { System.out.println(((ButtonType)modelObj).getHref()); } // write to a file Marshaller marshaller = context.createMarshaller(); marshaller.setProperty("jaxb.formatted.output", Boolean.TRUE); marshaller.marshal(panel, new FileOutputStream(outputFile));
23
JAXB RI: Using it (II) ObjectFactory factory = new ObjectFactory(); PanelType topLevelPanel = factory.createPanel(); ButtonType nestedButton = factory.createPanelTypeButton(); PanelType nestedPanel = factory.createPanelTypePanel(); LabelType nestedLabel = factory.createPanelTypeLabel(); nestedButton.setHref("http://apachecon.com/2005/US/images/apachefeather_sm.gif"); nestedLabel.setAlignment("center"); nestedLabel.setValue("Some other text"); topLevelPanel.getButtonOrLabelOrPanel().add(nestedButton); topLevelPanel.getButtonOrLabelOrPanel().add(nestedPanel); topLevelPanel.getButtonOrLabelOrPanel().add(nestedLabel); LabelType deepNestedLabel = factory.createPanelTypeLabel(); ButtonType deepNestedButton = factory.createPanelTypeButton(); deepNestedLabel.setValue("Some text"); deepNestedButton.setText("Click me"); nestedPanel.getButtonOrLabelOrPanel().add(factory.createPanelTypePanel()); nestedPanel.getButtonOrLabelOrPanel().add(deepNestedLabel); nestedPanel.getButtonOrLabelOrPanel().add(deepNestedButton);
24
JAXB RI: Customizing <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc"> <jxb:bindings schemaLocation="gui.xsd„ node="/xsd:schema"> <jxb:bindings node="//xsd:complexType[@name='panel-type'] /xsd:sequence/xsd:any">
25
JAXB 2 RI: New stuff Adds the new annotation-driven binding facility which generates only annotated classes The object factory is no longer required (though still available) Lots of other improvements Generates types for Schema simple types Automatic mapping of xsd:any to DOM Better complex type handling
26
JAXB 2 RI: Generated code (I) @XmlAccessorType(AccessType.FIELD) @XmlType(name = "label-type") public class LabelType { @XmlValue protected String value; @XmlAttribute protected LabelAlignmentType alignment; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public LabelAlignmentType getAlignment() { return alignment; } public void setAlignment(LabelAlignmentType value) { this.alignment = value; }
27
JAXB 2 RI: Generated code (II) @XmlEnum(String.class) public enum LabelAlignmentType { @XmlEnumValue("center") CENTER("center"), @XmlEnumValue("left") LEFT("left"), @XmlEnumValue("right") RIGHT("right"); public final String value; LabelAlignmentType(String v) { value = v; }
28
JaxMe 2 The first Apache project ;-) JAXB1 implementation, currently version 0.5 http://ws.apache.org/jaxme http://ws.apache.org/jaxme Only available open source implementation (aside from the RI) Not complete yet No support for model groups with maxOccurs > 1 No support for xsd:any elements No support for external binding files
29
JaxMe 2: Schema Changes <xsd:element name="button" type="gui:button-type" minOccurs="0"/> <xsd:element name="label" type="gui:label-type" minOccurs="0"/> <xsd:element name="panel" type="gui:panel-type" minOccurs="0"/>
30
JaxMe 2: Generated code public interface PanelType { public test.jaxme.ButtonType getButton(); public void setButton(test.jaxme.ButtonType pButton); public test.jaxme.LabelType getLabel(); public void setLabel(test.jaxme.LabelType pLabel); public test.jaxme.PanelType getPanel(); public void setPanel(test.jaxme.PanelType pPanel); }
31
JaxMe 2: Differences to the RI (I) Generated implementation classes are a lot more readable Integrates with databases (XML, relational) Provides additional functionality JaxMeAPI – Clean-room implementation of the JAXB 1 API under Apache license JaxMeJS – Source generation framework JaxMeXS – Schema parser component JaxMePM – Persistence management functionality for reading/writing JAXB objects from/to databases
32
JaxMe 2: Differences to the RI(II) public class LabelTypeImpl implements test.jaxme.LabelType { private java.lang.String _alignment = "left"; private java.lang.String _value; public java.lang.String getAlignment() { return _alignment; } public void setAlignment(java.lang.String pAlignment) { _alignment = pAlignment; } public java.lang.String getValue() { return _value; } public void setValue(java.lang.String pValue) { _value = pValue; }
33
JaxMe 2: Outlook Development is ongoing, but there are currently only few developers Upcoming features will make JaxMe really useable JAXME-61: maxOccurs > 1 JAXME-66: wildcards / xjc:dom
34
XMLBeans http://xmlbeans.apache.org http://xmlbeans.apache.org Current released version is 2.0.0 Not compatible to JAXB, rather it can do more Provides 3 APIs to access the complete infoset of the XML simultaneously Generated Java classes XML Cursor API for navigation XPath & XQuery support Provides access to the Schema type system itself
35
XMLBeans: Generated code (I)
36
XMLBeans: Generated code (II) public interface ButtonType extends org.apache.xmlbeans.XmlObject { java.lang.String getText(); org.apache.xmlbeans.XmlString xgetText(); boolean isSetText(); void setText(java.lang.String text); void xsetText(org.apache.xmlbeans.XmlString text); void unsetText(); // same for href, type, show, actuate... public static final class Factory { public static test.xmlbeans.ButtonType newInstance() {... } public static test.xmlbeans.ButtonType parse(java.lang.String xmlAsString) throws org.apache.xmlbeans.XmlException {... } public static test.xmlbeans.ButtonType parse(java.io.File file) throws org.apache.xmlbeans.XmlException, java.io.IOException {... }... }
37
XMLBeans: Generated code (III) public interface PanelType extends org.apache.xmlbeans.XmlObject { java.util.List getButtonList(); test.xmlbeans.ButtonType[] getButtonArray(); test.xmlbeans.ButtonType getButtonArray(int i); int sizeOfButtonArray(); void setButtonArray(test.xmlbeans.ButtonType[] buttonArray); void setButtonArray(int i, test.xmlbeans.ButtonType button); test.xmlbeans.ButtonType insertNewButton(int i); test.xmlbeans.ButtonType addNewButton(); void removeButton(int i); // same for Label and Panel public static final class Factory {... }
38
XMLBeans: Using it // read from Xml PanelType panel = PanelType.Factory.parse(inputFile); // create the panel manually and write it to Xml PanelDocument panelDoc = PanelDocument.Factory.newInstance(); PanelType topLevelPanel = panelDoc.addNewPanel(); ButtonType nestedButton = topLevelPanel.addNewButton(); PanelType nestedPanel = topLevelPanel.addNewPanel(); LabelType nestedLabel = topLevelPanel.addNewLabel(); nestedButton.setHref("http://apachecon.com/2005/US/images/apachefeather_sm.gif"); nestedLabel.setAlignment(LabelAlignmentType.CENTER); nestedLabel.setStringValue("Some other text"); PanelType deepNestedPanel = nestedPanel.addNewPanel(); LabelType deepNestedLabel = nestedPanel.addNewLabel(); ButtonType deepNestedButton = nestedPanel.addNewButton(); deepNestedLabel.setStringValue("Some text"); deepNestedButton.setText("Click me"); panelDoc.save(outputFile, new XmlOptions().setSavePrettyPrint());
39
XMLBeans: Additional APIs // read from Xml PanelType panel = PanelType.Factory.parse(inputFile); XmlCursor cursor = panel.newCursor(); // now the cursor is at the start of the document cursor.toFirstChild(); // now at the start of the panel cursor.toEndToken(); // now just before the end of the panel cursor.insertElementWithText("documentation", "http://www.someotherlocation.net/example", "XMLBeans was here"); cursor.dispose(); // write to Xml panel.save(outputFile, new XmlOptions().setSavePrettyPrint());
40
XMLBeans: Benefits Full support of the XML Schema standard Fine grained access to the complete infoset of the XML document (including XML comments) Great documentation Unmarshalling is on-demand (incremental) Validation against the Schema is built into the generated classes
41
XMLBeans: Problems Generated code is complicated There is no easy way to extend the generated types
42
The sample model
43
XMLSerialization Valid option if XML structure is not important Conceptually equal to normal serialization but also portable XML structure is driven by Java model Uses reflection to extract information at runtime Extremely simple to use No Apache project Others: JSX (http://jsx.org) & XStreamhttp://jsx.org
44
XStream http://xstream.codehaus.org http://xstream.codehaus.org BSD license, current version is 1.1.2 Fully features serialization library Some core features Support for non-public fields (including private and final) Support for non-public and inner classes Classes are also not required to have default or no-argument constructor Support for Java 5 enumerations
45
XStream: Usage XStream xstream = new XStream(); Panel panel = getTestModel(); // write to file xstream.toXML(panel, new FileWriter(outputFile)); // read from file panel = (Panel)xstream.fromXML(new FileReader(inputFile));
46
XStream: Output http://apachecon.com/2005/US/images/apachefeather_sm.gif Some text 1 left Click me Some other text 1 center
47
XStream: Customization xstream.registerConverter(new Converter() { public boolean canConvert(Class type) { return AlignmentEnum.class.equals(type); } public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { writer.setValue(((AlignmentEnum)source).getName()); } public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { return AlignmentEnum.getEnum(reader.getValue()); } }); xstream.alias("panel", Panel.class); xstream.alias("label", Label.class); xstream.alias("button", Button.class); xstream.aliasField("text", Label.class, "_text"); xstream.aliasField("alignment", Label.class, "_alignment"); xstream.aliasField("text", Button.class, "_text"); xstream.aliasField("href", Button.class, "_imageUrl"); xstream.addImplicitCollection(Panel.class, "_children");
48
XStream: Customized output http://apachecon.com/2005/US/images/apachefeather_sm.gif Some text left Click me Some other text center
49
Java XML mapping Maps between (existing) Java classes and (pre-defined) XML structure Most flexible approach Mapping interpretation can be Generated and added to the Application Static mapping Interpreted at runtime (via reflection) Dynamic mapping Apache projects: commons-betwixt Others: JiBX, Javolution (http://javolution.org/)
50
JiBX http://jibx.sourceforge.net http://jibx.sourceforge.net license is BSD, current version is 1.0 RC1 Static mapping with bytecode enhancement External XML file defines mapping Also contains a Schema JiBX tool in alpha stage Creates Java classes & JiBX mapping from the Schema Both can then be adjusted as needed
51
JiBX: Mapping definition <collection field="_children“ item-type="test.model.ModelObject" type="java.util.ArrayList"/> <value style="attribute“ name="alignment“ usage="required" get-method="getAlignment“ set-method="setAlignment" serializer="test.AlignmentEnumConverter.alignmentEnumToString" deserializer="test.AlignmentEnumConverter.alignmentEnumFromString"/> <value style="attribute“ name="text“ usage="optional" get-method="getText“ set-method="setText"/> <value style="attribute“ name="href“ field="_imageUrl“ usage="optional“ ns="http://www.w3.org/1999/xlink“/>
52
JiBX: Customizing package test; import test.model.AlignmentEnum; public class AlignmentEnumConverter { public static String alignmentEnumToString(AlignmentEnum value) { return value.getName(); } public static AlignmentEnum alignmentEnumFromString(String value) { return AlignmentEnum.getEnum(value); }
53
JiBX: Usage IBindingFactory factory = BindingDirectory.getFactory(Panel.class); // write to XML IMarshallingContext marshaller = factory.createMarshallingContext(); marshaller.setIndent(4); marshaller.marshalDocument(getTestModel(), "ISO-8859-1", null, new FileWriter(outputFile)); // read from XML IUnmarshallingContext unmarshaller = factory.createUnmarshallingContext(); Panel panel = (Panel)unmarshaller.unmarshalDocument(new FileReader(inputFile), null);
54
JiBX: Output <button xmlns:xlink="http://www.w3.org/1999/xlink“ xlink:href="http://apachecon.com/2005/US/images/apachefeather_sm.gif"/> Some text Some other text
55
JiBX: Benefits & Problems Benefits It is fast because the mapping is compiled into code Mapping is powerful and easily customizable Problems Learning it takes time Maps only what is specified in the mapping Some quirks in the Ant task and commandline tool
56
Betwixt http://jakarta.apache.org/commons/betwixt http://jakarta.apache.org/commons/betwixt Current version is 0.7 Dynamic mapping tool Can be used like XML serializers without a mapping definition Mapping overrides in external files One per Class (.betwixt) In one file Uses commons-digester which allows for extended customization abilities
57
Betwixt: Basic usage (II) Panel panel = getTestModel(); // write to XML FileWriter output = new FileWriter(outputFile); BeanWriter writer = new BeanWriter(output); writer.enablePrettyPrint(); output.write(" \n"); writer.write(panel); output.close(); // read from XML BeanReader reader = new BeanReader(); reader.registerBeanClass(Panel.class); reader.registerBeanClass(Label.class); reader.registerBeanClass(Button.class); panel = (Panel)reader.parse(new FileReader(inputFile));
58
Betwixt: Basic usage (II) apachecon.com 80 /2005/US/images/apachefeather_sm.gif apachecon.com /2005/US/images/apachefeather_sm.gif http test.model.AlignmentEnum left 1 Some text Click me test.model.AlignmentEnum center 1 Some other text
59
Betwixt: Customization (I) FileWriter output = new FileWriter(outputFile); BeanWriter writer = new BeanWriter(output); writer.getBindingConfiguration().setObjectStringConverter( new AlignmentEnumStringConverter()); writer.getXMLIntrospector().getConfiguration().getPrefixMapper().setPrefix( "http://www.w3.org/1999/xlink", "xlink"); writer.getXMLIntrospector().register(new InputSource("mapping.xml")); writer.enablePrettyPrint(); output.write(" \n"); writer.write(panel); output.close(); BeanCreationList chain = BeanCreationList.createStandardChain(); BeanReader reader = new BeanReader(); chain.insertBeanCreator(1, new ButtonCreator()); reader.getReadConfiguration().setBeanCreationChain(chain); reader.getXMLIntrospector().getConfiguration().getPrefixMapper().setPrefix( "http://www.w3.org/1999/xlink", "xlink"); reader.registerMultiMapping(new InputSource("mapping.xml")); reader.getBindingConfiguration().setObjectStringConverter( new AlignmentEnumStringConverter()); panel = (Panel)reader.parse(new FileReader(inputFile));
60
Betwixt: Customization (II) public class ButtonCreator implements ChainedBeanCreator { public Object create(ElementMapping mapping, ReadContext context, BeanCreationChain chain) { return "button".equals(mapping.getName()) ? new Button(mapping.getAttributes().getValue("text")) : chain.create(mapping, context); } public class AlignmentEnumStringConverter extends ConvertUtilsObjectStringConverter { public String objectToString(Object object, Class type, Context context) { return AlignmentEnum.class.equals(type) ? ((AlignmentEnum)object).getName() : super.objectToString(object, type, context); } public Object stringToObject(String value, Class type, Context context) { return AlignmentEnum.class.equals(type) ? AlignmentEnum.getEnum(value) : super.stringToObject(value, type, context); }
61
Betwixt: Mapping file <attribute name=“href” property=“imageUrl” uri=“http://www.w3.org/1999/xlink”/>
62
Betwixt: Output <button xlink:href= "http://apachecon.com/2005/US/images/apachefeather_sm.gif" id="2" xmlns:xlink="http://www.w3.org/1999/xlink"/> Some text Some other text
63
Betwixt: Annotations (I) @XmlElement(localName = "panel") public class Panel implements ModelObject { private List _children = new ArrayList(); @XmlCollection(updater = "addChild") public List getChildren() { return _children; } public void setChildren(List children) { _children = children; } public void addChild(ModelObject obj) { _children.add(obj); }
64
Betwixt: Annotations (II) @XmlElement(localName = "label") public class Label extends VisualModelObject { private String _text; private AlignmentEnum _alignment;... public String getText() { return _text; } @XmlText() public void setText(String text) { _text = text; } public AlignmentEnum getAlignment() { return _alignment; } @XmlAttribute(localName = "alignment") public void setAlignment(AlignmentEnum alignment) { _alignment = alignment; }
65
Betwixt: Annotations (III) Panel panel = getTestModel(); FileWriter writer = new FileWriter(outputFile); BeanWriter beanWriter = new BeanWriter(writer); XMLIntrospector introspector = new AnnotationIntrospector(); introspector.getConfiguration().getPrefixMapper().setPrefix( "http://www.w3.org/1999/xlink", "xlink"); beanWriter.setXMLIntrospector(introspector); beanWriter.getBindingConfiguration().setObjectStringConverter( new AlignmentEnumStringConverter()); beanWriter.enablePrettyPrint(); beanWriter.setWriteEmptyElements(true); writer.write(" \n"); beanWriter.write(panel); writer.close();
66
Betwixt: Benefits & Problems Benefits Works reasonably out-of-the-box Mapping definition is relatively simple Powerful customizations Annotations make mapping simpler Can map to DynaBeans Problems Bean-centric Reading/writing seems more complicated Slow Docs need enhancement
67
Performance Performance is important but not a focus of this talk - still … Performance of the approaches differs a lot Comparing them is not really fair General observations Generated (byte)code usually leads to good performance Binding at tuntime (dynamic mapping) is a slower but usually more flexible Might be a choice between speed and flexibility
68
Choosing the ‘right’ approach Depends on what is fixed, XML and/or Java If XML is fixed If XML structure is complex Schema Java compiler Else Java – XML Mapping If Java is fixed If XML structure is not important XML Serialization Else Java – XML Mapping
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.