The Java Architecture For XML Binding JAXB By

The Java Architecture For (XML Binding (JAXB By: Yoav Zibin Sharon Krisher

Motivation for JAXB n The main purpose of XML Schema is: ¨ n Validation of XML documents Any other purposes? ¨ ¨ Hint 1: determinism requirement Hint 2: the “default” attribute has nothing to do with validation <xs: attribute name="country" use=“optional” default="Israel“ /> n Answer: Given a valid XML document, its schema defines a unique data model

Motivation for JAXB n n Problem: How to manipulate this data model? DOM (data object model) solution: ¨ ¨ Pros: simple, general (a schema is not even required) Cons: no types, no compile-time checking DOM pseudo-code example root. get. Child("Address"). get. Child("Number"). get. Text() n I wish to write … returns a string root. get. Address(). get. Number() returns a number

JAXB solution: Mapping XML Schema to Java interfaces Binding Compiler Source schema Java interfaces Pros: preserve types, compile-time checking Cons: complex, specific to a certain schema

<xs: complex. Type name="Address. Type"> <xs: sequence> <xs: element name="Number" type="xs: unsigned. Int"/> <xs: element name="Street" type="xs: string"/> </xs: sequence> </xs: complex. Type> Binding Compiler public interface Address. Type { long get. Number(); void set. Number(long value); String get. Street(); void set. Street(String value); } Must be non-negative Must be non-null

Talk Outline n How is XML Schema mapped to Java interfaces? What is the default mapping? ¨ How to customize this mapping? ¨ Second part of the lecture ¨ n How do I use those Java interfaces? ¨ Next slides and a Demo!

Main Features Unmarshal: xml objects n Create / Read / Update / Delete objects n Validate objects n Marshal: objects xml n No roundtrip guarantees n Marshal( Unmarshal(xml) ) ≠ xml ¨ We found that order is not always preserved ¨ But usually roundtrip holds ¨

Step 1: Create XML Schema Demo. xsd <xs: element name="Person" type="Person. Type"/> <xs: complex. Type name="Person. Type"> <xs: sequence> <xs: element name=“Name" type="xs: string"/> <xs: element name="Address" type="Address. Type" min. Occurs="1" max. Occurs="unbounded"/> </xs: sequence> </xs: complex. Type> <xs: complex. Type name="Address. Type"> <xs: sequence> <xs: element name="Number" type="xs: unsigned. Int"/> <xs: element name="Street" type="xs: string"/> </xs: sequence> </xs: complex. Type>

Step 2: Create XML Document Demo. xml <Person xmlns: xsi="http: //www. w 3. org/2001/XMLSchema-instance" xsi: no. Namespace. Schema. Location="C: JAXB Demodemo. xsd"> <Name>Sharon Krisher</Name> <Address> <Street>Iben Gevirol</Street> <Number>57</Number> </Address> <Street>Moshe Sharet</Street> <Number>89</Number> </Address> </Person> Check that your XML conforms to the Schema

Step 3: Run the binding compiler n %JWSDP_HOME%jaxbbinxjc -p demo. xsd ¨ A package named demo is created (in the directory demo) ¨ The package contains (among other things): interface Address. Type n interface Person. Type n

Address. Type and Person. Type public interface Address. Type { long get. Number(); void set. Number(long value); Must be non-negative String get. Street(); void set. Street(String value); } Must be non-null public interface Person. Type { String get. Name(); void set. Name(String value); /* List of Address. Type */ java. util. List get. Address(); } In Java 1. 5: List<Address. Type> Must be non-null Must contain at least one item

Step 4: Create Context The context is the entry point to the API n Contains methods to create Marshaller, Unmarshaller and Validator instances n JAXBContext context = JAXBContext. new. Instance("demo"); The package name is demo (Recall: xjc -p demo. xsd)

Step 5: Unmarshal: xml -> objects Unmarshaller unmarshaller = context. create. Unmarshaller(); unmarshaller. set. Validating(true); Enable validation of xml according to the schema while unmarshalling Person. Type person = (Person. Type) unmarshaller. unmarshal( new File. Input. Stream("demo. xml") );

Step 6: Read System. out. println("Person name=" + person. get. Name() ); Address. Type address = (Address. Type) person. get. Address(). get(0); System. out. println("First Address: " + " Street=" + address. get. Street() + " Number=" + address. get. Number() );

Step 7: Manipulate objects // Update person. set. Name("Yoav Zibin"); // Delete List address. List = person. get. Address(); address. List. clear(); What happens if we validate there? // Create Object. Factory object. Factory = new Object. Factory(); Address. Type new. Addr = object. Factory. create. Address. Type(); new. Addr. set. Street("Hanoter"); new. Addr. set. Number(5); address. List. add( new. Addr ); part of the demo package uses the factory pattern

Step 8: Validate on-demand Validator validator = context. create. Validator(); validator. validate(new. Addr); Check that we have set Street and Number, and that Number is non-negative validator. validate(person); Check that we have set Name, and that Address contains at least one item

Step 9: Marshal: objects -> xml Marshaller marshaller = context. create. Marshaller(); marshaller. set. Property(Marshaller. JAXB_FORMATTED_OUTPUT, Boolean. TRUE); marshaller. marshal(person, new File. Output. Stream("output. xml")); output. xml <Person> <Name>Yoav Zibin</Name> <Address> <Street>Hanoter</Street> <Number>5</Number> </Address> </Person>

!And now, the Demo

First Part Summary

Similar Technologies n Liquid XML Data Binding Similar to JAXB ¨ Supports all Schema constructs ¨ In addition to Java: C#, C++, Visual Basic 6 ¨ n Relaxer ¨ n Instead of Schema uses Relax Castor. org

Second Part Outline Validation n Mapping XML Schema to Java n Naming ¨ Java Properties ¨ Simple and Complex Types ¨ n Customization of the default mapping

Validation Constraints n Three categories of constraints ¨ Type constraints: Legal values in simple types n ¨ Local structural constraints n ¨ E. g. , in every address, number is a non-negative integer E. g. , in every person, address contains at least one item Global structural constraints n E. g. , ID and IDREF

Validation n Three forms of validation ¨ ¨ Unmarshal time validation (at unmarshal time) On-demand validation (at any chosen point in time) n n ¨ Fail-fast validation (at all times) n n validate. Root(object) vs. validate(object) validate. Root includes global constraint checking Currently not implemented Checks that the value provided to a set method is legal When validation errors occur an event is raised (no exception) and validation continues, so that several validation errors can be handled. Default handler raises an exception on first error

Unsupported Schema Concepts Substitution groups n Type substitutions (xsi: type, block) n Key, keyref, and unique n any. Attribute n n No support for XPath or any other query langauge

Element vs. Type n An element also has a qualified name <xs: element name=“ugly_man" type="Person. Type"/> <xs: element name=“pretty_woman" type="Person. Type"/> <xs: complex. Type name="Person. Type"> … </xs: complex. Type> an empty interface which marks the existence of a static QName interface Ugly. Man extends Person. Type, Element {} interface Pretty. Woman extends Person. Type, Element {} interface Person. Type { … } n When is the difference important? (next)

? When must I use elements n Marshal: marshaller. marshal(Object, Output. Stream) E. g. , when we marshal a Person. Type: <Name>Sharon Krisher</Name> <Address> <Street>Iben Gevirol</Street> <Number>57</Number> </Address> n must be an element, otherwise the resulting output is not a legal XML General content <xs: any/> Object get. Any(); void set. Any(Object element. Or. Value);

Naming n Problem: sometimes XML names are not legal java names ¨ do not comply to java naming standards ¨ n The binding compiler creates proper names XML Name Class Name Method Name mixed. Case. Name Mixed. Case. Name get. Mixed. Case. Name name-with-dash Name. With. Dash get. Name. With. Dash aa_bb-cc Aa. Bb. Cc get. Aa. Bb. Cc

Java Properties n Local schema components are mapped to: ¨ Simple property (get, set) String get. Name(); void set. Name(String value); n ¨ With customization: is. Set. Name , unset. Name List property java. util. List get. Address(); ¨ Indexed property (next) In Java 1. 5: List<Address. Type>

Indexed Property n Used instead of a list property when a proper customization is applied Address. Type[] get. Address(); void set. Address(Address. Type[] value); Address. Type get. Address(int index); void set. Address(int index, Address. Type value);

General Content Property n The most general content property ¨ ¨ n Can represent any content, however complex A list that can contain element interfaces and values Used for “problematic cases” : ¨ Name collisions due to derivation Mixed content ¨ Another example: ¨ <xs: any max. Occurs="unbounded"/> Each item can be some element or value List get. Any();

(Simple Types (partial diagram Simple. Type Primtive ID/IDREF date integer List Union List Next (1) String/Object Calendar Restriction Represented as validation constraints max. Inclusive Big. Integer Enumeration int Next (2)

Simple Type: Union <xs: complex. Type name="Date"> <xs: sequence> <xs: element name="Month"> <xs: simple. Type> <xs: union member. Types="xs: int xs: string"/> </xs: simple. Type> </xs: element> </xs: sequence> </xs: complex. Type> Public interface Date { Object get. Month(); void set. Month(Object); } Common supertype of (Integer, String) is Object

Type Safe Enumeration <xs: simple. Type name="USState"> <xs: restriction base="xs: NCName"> <xs: enumeration value="AK"/> <xs: enumeration value="NY"/> </xs: restriction> </xs: simple. Type> public class USState { protected USSate(String v) {…} public static final USState AK = …; public static final USState NY = …; public String get. Value(); public static USState from. Value(String v) {…} }

XML Schema Type System Any Simple. Type finished Complex. Type Simple. Content Complex. Content *Extension *Sequence * Choice Extension Restriction * ( ) Next Represented as a Java interface The interface extends the base type’s interface * All Elements Attributes use default fixed * * abstract nillable min. Occurs max. Occurs Represented as Java properties

Complex Types Represented as a Java interface n Anonymous type n An interface is created. ¨ The name is derived from the name of the schema element + “Type”, e. g Foo. Type ¨ n Abstract types: no create method in Object. Factory

Complex Type: Simple Content <xs: complex. Type name=“International. Price"> <xs: simple. Content> <xs: extension base="xs: int"> <xs: attribute name="currency“ type="xs: string"/> </xs: extension> </xs: simple. Content> </xs: complex. Type> interface International. Price { int get. Value(); void set. Value(int); String get. Currency(); void set. Currency(String); }

Complex Type: Aggregation <xs: element name="A" type="xs: int"/> <xs: complex. Type name="Foo"> <xs: sequence> <xs: element ref="A"/> <xs: sequence> <xs: element ref="B"/> <xs: element ref="C"/> </xs: sequence> </xs: complex. Type> <xs: complex. Type name="Foo"> <xs: sequence> <xs: element ref="A"/> <xs: element ref="B"/> <xs: element ref="C"/> </xs: sequence> </xs: complex. Type> interface Foo { int get. A(); void set. A(int); int get. B(); void set. B(int); int get. C(); void set. C(int); }

Complex Type: Mixed Content <xs: complex. Type name=“Letter. Body" mixed="true"> <xs: sequence> <xs: element name="name" type="xs: string"/> … </xs: sequence> XML fragment </xs: complex. Type> Dear Mr. <name>Robert Smith</name>, … interface lb Letter. Body { Letter. Body = Object. Factory. create. Letter. Body(); interface Name extends Element { List gcl = lb. get. Content(); String get. Value(); gcl. add("Dear Mr. "); void set. Value(String); gcl. add(Object. Factory. create. Letter. Body. Name("Robert Smith")); } … The list may contain List get. Content(); elements and strings }

Complex Type: Choice <xs: complex. Type name="Foo. Bar. Type"> The programmer <xs: choice> is responsible to <xs: element name="Foo" type="xs: int"/> only set one of <xs: element name="Bar" Foo or Bar type="xs: string"/> </xs: choice> Default </xs: complex. Type> public interface Foo. Bar. Type { Customization (Not implemented yet) int get. Foo(); public interface Foo. Bar. Type { void set. Foo(int value); Object get. Foo. Or. Bar(); String get. Bar(); void set. Foo. Or. Bar(Object); void set. Bar(String value); } Common supertype of (Integer, String) is Object Similar to union boolean is. Set. Foo(); void unset. Foo(); boolean is. Set. Bar(); void unset. Bar(); }

When max. Occurs>1 <xs: complex. Type name="Foo. Bar. Type"> <xs: choice max. Occurs="unbounded"> <xs: element name="Foo" type="xs: int"/> <xs: element name="Bar" type="xs: string"/> </xs: choice> </xs: complex. Type> public interface Foo. Bar. Type { interface Foo extends Element {…} interface Bar extends Element {…} // Items are instances of Foo and Bar List get. Foo. Or. Bar(); } For a sequence: List get. Foo. And. Bar() The programmer needs to make sure that the list contains sequences of <A, B>.

Complex Type: All n n Mapped like Sequence Can’t have max. Occurs > 1 No way to specify the order of elements Round trip doesn’t hold (order is not preserved): unmarshal XML ≠ XML Objects in memory marshal

Nillable elements <xs: element name=“age" type=“xs: int" nillable="true"/> Integer get. Age(); void set. Age(Integer value); Java: set. Age( new Integer(25) ) or set. Age(null) XML: <age>25</age> or <age xsi: nil="true"/>

Customization Used to augment the default mapping n Customizations declared via special xml tags n May appear inside the source schema or in a separate file n

Uses of Customization n Change default names of interfaces and properties For a specific schema construct ¨ For an entire namespace ¨ n Add a suffix or a prefix Change the types of properties n Add javadoc declarations n

Software Engineering Issues n Weak Typing Our suggestions: Marshal / Unmarshal : Object Element ¨ IDREF: Object Identifiable ¨ n Sometimes JAXB doesn’t allow us to control the order of elements Example 1: xs: all ¨ Example 2: next slide ¨

Element Order Example <xs: complex. Type name=“ABType"> <xs: choice> <xs: sequence> <xs: element name="A" type="xs: int"/> <xs: element name="B" type="xs: string"/> </xs: sequence> <xs: element name="B" type="xs: string"/> <xs: element name="A" type="xs: int"/> </xs: sequence> </xs: choice> </xs: complex. Type> public interface ABType { int get. A(); void set. A(int value); String get. B(); void set. B(String value); } obj. set. A(5); obj. set. B(“a”); What happens when we marshal obj? No roundtrip

It’s the programmer’s fault n Taken from JAXB specification: “The caller must be sure …” ¨ “There is an expectation …” ¨ “User is responsible …” ¨ “… unexpected behavior may occur. ” ¨ Question: What is the output? xs: choice between Foo and Bar obj. set. Age(42); 42 true obj. set. Foo(42); obj. unset. Age(); obj. set. Bar("A"); System. out. println( obj. get. Age() ); ); System. out. println( obj. is. Set. Foo()

The END n Any questions?
- Slides: 48