the java architecture for xml binding (jaxb) by: yoav zibin sharon krisher

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

Upload: winifred-matthews

Post on 17-Dec-2015

235 views

Category:

Documents


1 download

TRANSCRIPT

The Java Architecture For XML Binding (JAXB)

By:Yoav Zibin

Sharon Krisher

Motivation for JAXB

The main purpose of XML Schema is: 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“ />

Answer: Given a valid XML document, its schema defines a unique data model

Motivation for JAXB

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

I wish to write …

root.getChild("Address").getChild("Number").getText()

DOM pseudo-code example

root.getAddress().getNumber()

returns a number

returns a string

Binding Compiler

Java interfaces

Java interfaces

Source schema

Source schema

JAXB solution: Mapping XML Schema to Java interfaces

Pros: preserve types, compile-time checkingCons: complex, specific to a certain schema

Binding Compiler

<xs:complexType name="AddressType"> <xs:sequence> <xs:element name="Number" type="xs:unsignedInt"/> <xs:element name="Street" type="xs:string"/> </xs:sequence></xs:complexType>

public interface AddressType { long getNumber(); void setNumber(long value);

String getStreet(); void setStreet(String value);}

Must be non-negative

Must be non-null

Talk Outline

How is XML Schema mapped to Java interfaces? What is the default mapping? How to customize this mapping? Second part of the lecture

How do I use those Java interfaces? Next slides and a Demo!

Main Features

Unmarshal: xml objects Create / Read / Update / Delete objects Validate objects Marshal: objects xml No roundtrip guarantees

Marshal( Unmarshal(xml) ) ≠ xml We found that order is not always preserved But usually roundtrip holds

Step 1: Create XML Schema

<xs:element name="Person" type="PersonType"/> <xs:complexType name="PersonType"> <xs:sequence> <xs:element name=“Name" type="xs:string"/> <xs:element name="Address" type="AddressType" minOccurs="1" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:complexType name="AddressType"> <xs:sequence> <xs:element name="Number" type="xs:unsignedInt"/> <xs:element name="Street" type="xs:string"/> </xs:sequence></xs:complexType>

Demo.xsd

Step 2: Create XML Document

<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="C:\JAXB Demo\demo.xsd">

<Name>Sharon Krisher</Name><Address>

<Street>Iben Gevirol</Street><Number>57</Number>

</Address><Address>

<Street>Moshe Sharet</Street><Number>89</Number>

</Address></Person>

Check that your XML conforms to the Schema

Demo.xml

Step 3: Run the binding compiler

%JWSDP_HOME%\jaxb\bin\xjc -p demo demo.xsd A package named demo is created

(in the directory demo) The package contains (among other things):

interface AddressType interface PersonType

AddressType and PersonTypepublic interface AddressType { long getNumber(); void setNumber(long value);

String getStreet(); void setStreet(String value);}

public interface PersonType { String getName(); void setName(String value);

/* List of AddressType */ java.util.List getAddress(); }

In Java1.5: List<AddressType>

Must contain at least one item

Must be non-negative

Must be non-null

Must be non-null

Step 4: Create Context

The context is the entry point to the API Contains methods to create Marshaller,

Unmarshaller and Validator instances

JAXBContext context = JAXBContext.newInstance("demo");

The package name is demo

(Recall: xjc -p demo demo.xsd)

Step 5: Unmarshal: xml -> objects

Unmarshaller unmarshaller = context.createUnmarshaller();

unmarshaller.setValidating(true);

PersonType person = (PersonType) unmarshaller.unmarshal(

new FileInputStream("demo.xml") );

Enable validation of xml according to the

schema while unmarshalling

Step 6: Read

System.out.println("Person name=" + person.getName() );

AddressType address = (AddressType) person.getAddress().get(0);

System.out.println("First Address: " +" Street=" + address.getStreet() + " Number=" + address.getNumber() );

Step 7: Manipulate objects// Update

person.setName("Yoav Zibin");

// Delete

List addressList = person.getAddress();

addressList.clear();

part of the demo package

uses the factory pattern

// Create

ObjectFactory objectFactory = new ObjectFactory();

AddressType newAddr = objectFactory.createAddressType();

newAddr.setStreet("Hanoter");

newAddr.setNumber(5);

addressList.add( newAddr );

What happens if we validate there?

Step 8: Validate on-demand

Validator validator = context.createValidator();

validator.validate(newAddr);

validator.validate(person);

Check that we have set Street and Number, and that Number is non-negative

Check that we have set Name, and that Address contains at least one item

Step 9: Marshal: objects -> xml

Marshaller marshaller = context.createMarshaller();

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,Boolean.TRUE);

marshaller.marshal(person, new FileOutputStream("output.xml"));

<Person> <Name>Yoav Zibin</Name> <Address> <Street>Hanoter</Street> <Number>5</Number> </Address></Person>

output.xml

And now, the Demo!

First Part Summary

Similar Technologies

Liquid XML Data Binding Similar to JAXB Supports all Schema constructs In addition to Java: C#, C++, Visual Basic 6

Relaxer Instead of Schema uses Relax

Castor.org

Second Part Outline

Validation Mapping XML Schema to Java

Naming Java Properties Simple and Complex Types

Customization of the default mapping

Validation Constraints

Three categories of constraints Type constraints: Legal values in simple types

E.g., in every address, number is a non-negative integer

Local structural constraints E.g., in every person, address contains at least

one item Global structural constraints

E.g., ID and IDREF

Validation

Three forms of validation Unmarshal time validation (at unmarshal time) On-demand validation (at any chosen point in time)

validateRoot(object) vs. validate(object) validateRoot includes global constraint checking

Fail-fast validation (at all times) 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 Type substitutions (xsi:type, block) Key, keyref, and unique anyAttribute

No support for XPath or any other query langauge

Element vs. Type

An element also has a qualified name

When is the difference important? (next)

<xs:element name=“ugly_man" type="PersonType"/> <xs:element name=“pretty_woman" type="PersonType"/><xs:complexType name="PersonType"> … </xs:complexType>

interface UglyMan extends PersonType, Element {} interface PrettyWoman extends PersonType, Element {}interface PersonType { … }

an empty interface which marks the existence of a static QName

When must I use elements ?

Marshal:

General content

marshaller.marshal(Object, OutputStream)

must be an element,otherwise the resulting

output is not a legal XML

<xs:any/> Object getAny();void setAny(Object elementOrValue);

<Name>Sharon Krisher</Name><Address>

<Street>Iben Gevirol</Street><Number>57</Number>

</Address>

E.g., when we marshal a PersonType:

Naming

Problem: sometimes XML names are not legal java names do not comply to java naming standards

The binding compiler creates proper names

XML NameClass NameMethod Name

mixedCaseNameMixedCaseNamegetMixedCaseName

name-with-dashNameWithDashgetNameWithDash

aa_bb-ccAaBbCcgetAaBbCc

Java Properties

Local schema components are mapped to: Simple property (get, set)

With customization: isSetName , unsetName List property

Indexed property (next)

java.util.List getAddress();

String getName();void setName(String value);

In Java1.5: List<AddressType>

Indexed Property

Used instead of a list property when a proper customization is applied

AddressType[] getAddress();void setAddress(AddressType[] value);

AddressType getAddress(int index);void setAddress(int index, AddressType value);

General Content Property

The most general content property 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 maxOccurs="unbounded"/>

List getAny();

Each item can be some element or

value

Simple Types (partial diagram)SimpleType

Primtive List Union Restriction

ID/IDREF

maxInclusive

Enumeration

date

integer

int

Calendar

BigInteger

int

String/Object

ListRepresented as validation constraints

Next (1)

Next (2)

Simple Type: Union<xs:complexType name="Date"> <xs:sequence> <xs:element name="Month"> <xs:simpleType> <xs:union memberTypes="xs:int xs:string"/> </xs:simpleType> </xs:element> </xs:sequence></xs:complexType>

Public interface Date { Object getMonth(); void setMonth(Object);}

Common supertype of (Integer, String) is Object

Type Safe Enumeration<xs:simpleType name="USState"> <xs:restriction base="xs:NCName"> <xs:enumeration value="AK"/> <xs:enumeration value="NY"/> </xs:restriction></xs:simpleType>

public class USState { protected USSate(String v) {…} public static final USState AK = …; public static final USState NY = …; public String getValue(); public static USState fromValue(String v) {…}}

XML Schema Type SystemAny

SimpleType ComplexType

SimpleContent ComplexContent Sequence Choice All

Extension Extension

RestrictionAttributes

use default fixed

Elements

abstract nillable minOccurs maxOccurs

finishedRepresented as a Java interface

The interface extends the base type’s interface Represented as

Java properties

*

* *

( ) Next*

**

*

Complex Types

Represented as a Java interface Anonymous type

An interface is created. The name is derived from the name of the

schema element + “Type”, e.g Foo FooType Abstract types: no create method in

ObjectFactory

Complex Type: Simple Content

interface InternationalPrice {int getValue();void setValue(int);

String getCurrency();void setCurrency(String);

}

<xs:complexType name=“InternationalPrice"> <xs:simpleContent> <xs:extension base="xs:int"> <xs:attribute name="currency“ type="xs:string"/> </xs:extension> </xs:simpleContent></xs:complexType>

Complex Type: Aggregation

<xs:complexType name="Foo"> <xs:sequence> <xs:element ref="A"/> <xs:sequence> <xs:element ref="B"/> <xs:element ref="C"/> </xs:sequence> </xs:sequence></xs:complexType>

interface Foo { int getA(); void setA(int); int getB(); void setB(int); int getC(); void setC(int); }

<xs:element name="A" type="xs:int"/>

<xs:complexType name="Foo"> <xs:sequence> <xs:element ref="A"/>

<xs:element ref="B"/> <xs:element ref="C"/>

</xs:sequence></xs:complexType>

Complex Type: Mixed Content

<xs:complexType name=“LetterBody" mixed="true"> <xs:sequence> <xs:element name="name" type="xs:string"/> … </xs:sequence></xs:complexType>

interface LetterBody { interface Name extends Element { String getValue(); void setValue(String); } … List getContent();}

Dear Mr.<name>Robert Smith</name>, …

XML fragment

The list may contain elements and strings

LetterBody lb = ObjectFactory.createLetterBody();List gcl = lb.getContent();gcl.add("Dear Mr.");gcl.add(ObjectFactory.createLetterBodyName("Robert Smith"));

Complex Type: Choice<xs:complexType name="FooBarType"> <xs:choice> <xs:element name="Foo" type="xs:int"/> <xs:element name="Bar" type="xs:string"/> </xs:choice></xs:complexType>

public interface FooBarType { Object getFooOrBar(); void setFooOrBar(Object);}

Common supertype of (Integer, String) is ObjectSimilar to union

public interface FooBarType { int getFoo(); void setFoo(int value); String getBar(); void setBar(String value); boolean isSetFoo(); void unsetFoo(); boolean isSetBar(); void unsetBar();}

The programmer is responsible to only set one of Foo or Bar

Default

Customization (Not implemented yet)

When maxOccurs>1

public interface FooBarType { interface Foo extends Element {…} interface Bar extends Element {…} // Items are instances of Foo and Bar List getFooOrBar();}

<xs:complexType name="FooBarType"> <xs:choice maxOccurs="unbounded"> <xs:element name="Foo" type="xs:int"/> <xs:element name="Bar" type="xs:string"/> </xs:choice></xs:complexType>

For a sequence: List getFooAndBar()The programmer needs to make sure thatthe list contains sequences of <A,B>.

Complex Type: All

Mapped like Sequence Can’t have maxOccurs > 1 No way to specify the order of elements Round trip doesn’t hold (order is not preserved):

XML

Objects in

memoryXML

unmarshal

marshal

Nillable elements

<xs:element name=“age" type=“xs:int" nillable="true"/>

Integer getAge();void setAge(Integer value);

<age xsi:nil="true"/>XML: <age>25</age> or

setAge(null)Java: setAge( new Integer(25) ) or

Customization

Used to augment the default mapping Customizations declared via special xml

tags May appear inside the source schema or

in a separate file

Uses of Customization

Change default names of interfaces and properties For a specific schema construct For an entire namespace

Add a suffix or a prefix

Change the types of properties Add javadoc declarations

Software Engineering Issues

Weak Typing Our suggestions: Marshal / Unmarshal : Object Element IDREF: Object Identifiable

Sometimes JAXB doesn’t allow us to control the order of elements Example 1: xs:all Example 2: next slide

Element Order Example<xs:complexType name=“ABType"> <xs:choice> <xs:sequence> <xs:element name="A" type="xs:int"/> <xs:element name="B" type="xs:string"/> </xs:sequence> <xs:sequence> <xs:element name="B" type="xs:string"/> <xs:element name="A" type="xs:int"/> </xs:sequence> </xs:choice></xs:complexType>

public interface ABType { int getA(); void setA(int value); String getB(); void setB(String value);}

obj.setA(5);obj.setB(“a”);

What happens when we marshal obj?

No roundtrip

It’s the programmer’s fault

Taken from JAXB specification: “The caller must be sure …” “There is an expectation …” “User is responsible …” “… unexpected behavior may occur.”

42obj.setAge(42);

obj.unsetAge();

System.out.println( obj.getAge() );

Question: What is the output ?

obj.setFoo(42);obj.setBar("A");System.out.println( obj.isSetFoo() );

xs:choice between Foo and Bartrue

The END

Any questions?