Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java-XML binding Apache © 2005 Thomas Dudziak

Similar presentations


Presentation on theme: "Java-XML binding Apache © 2005 Thomas Dudziak"— Presentation transcript:

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


Download ppt "Java-XML binding Apache © 2005 Thomas Dudziak"

Similar presentations


Ads by Google