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
DOM pseudo-code example
[Link]("Address").getChild("Number").getText()
I wish to write … returns a string
[Link]().getNumber()
returns a number
JAXB solution:
Mapping XML Schema to Java interfaces
Binding Compiler
Source Java
schema interface
s
Pros: preserve types, compile-time checking
Cons: complex, specific to a certain schema
<xs:complexType name="AddressType">
<xs:sequence>
<xs:element name="Number" type="xs:unsignedInt"/>
<xs:element name="Street" type="xs:string"/>
</xs:sequence>
</xs:complexType>
Binding Compiler
public interface AddressType {
long getNumber();
void setNumber(long value);
Must be non-negative
String getStreet();
void setStreet(String value);
} 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
[Link]
<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>
Step 2: Create XML Document
[Link]
<Person
xmlns:xsi="[Link]
xsi:noNamespaceSchemaLocation="C:\JAXB Demo\[Link]">
<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
Step 3: Run the binding compiler
%JWSDP_HOME%\jaxb\bin\xjc -p demo [Link]
A package named demo is created
)in the directory demo)
The package contains )among other things):
interface AddressType
interface PersonType
AddressType and PersonType
public interface AddressType {
Must be non-negative
long getNumber();
void setNumber(long value);
String getStreet();
void setStreet(String value);
}
Must be non-null
public interface PersonType { Must be non-null
String getName();
void setName(String value);
/* List of AddressType */ Must contain at least one item
[Link] getAddress();
}
In Java1.5: List<AddressType>
Step 4: Create Context
The context is the entry point to the API
Contains methods to create Marshaller,
Unmarshaller and Validator instances
JAXBContext context = [Link]("demo");
The package name is demo
)Recall: xjc -p demo [Link])
Step 5: Unmarshal: xml -> objects
Unmarshaller unmarshaller = Enable validation of
[Link](); xml according to the
schema while
[Link](true); unmarshalling
PersonType person =
(PersonType) [Link](
new FileInputStream("[Link]") );
Step 6: Read
[Link]("Person name=" +
[Link]() );
AddressType address = (AddressType)
[Link]().get(0);
[Link]("First Address: " +
" Street=" + [Link]() +
" Number=" + [Link]() );
Step 7: Manipulate objects
// Update
[Link]("Yoav Zibin");
// Delete
List addressList = [Link]();
[Link]();
What happens if we validate there?
// Create
ObjectFactory objectFactory = new ObjectFactory();
AddressType newAddr = [Link]();
[Link]("Hanoter");
part of the demo package
[Link](5);
[Link]( newAddr );
uses the factory pattern
Step 8: Validate on-demand
Validator validator = [Link]();
[Link](newAddr);
Check that we have set Street and Number,
and that Number is non-negative
[Link](person);
Check that we have set Name, and that
Address contains at least one item
Step 9: Marshal: objects -> xml
Marshaller marshaller = [Link]();
[Link](Marshaller.JAXB_FORMATTED_OUTPUT,
[Link]);
[Link](person,
new FileOutputStream("[Link]"));
[Link]
<Person>
<Name>Yoav Zibin</Name>
<Address>
<Street>Hanoter</Street>
<Number>5</Number>
</Address>
</Person>
!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
[Link]
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
<xs:element name=“ugly_man" type="PersonType"/>
<xs:element name=“pretty_woman" type="PersonType"/>
<xs:complexType name="PersonType"> … </xs:complexType>
an empty interface which marks
the existence of a static QName
interface UglyMan extends PersonType, Element {}
interface PrettyWoman extends PersonType, Element {}
interface PersonType { … }
When is the difference important? )next)
?When must I use elements
Marshal: [Link](Object, OutputStream)
E.g., when we marshal a PersonType:
<Name>Sharon Krisher</Name>
must be an element,
<Address>
<Street>Iben Gevirol</Street>
otherwise the resulting
<Number>57</Number> output is not a legal XML
</Address>
General content
<xs:any/> Object getAny();
void setAny(Object elementOrValue);
Naming
Problem: sometimes XML names
are not legal java names
do not comply to java naming standards
The binding compiler creates proper
names
XML Name Class Name Method Name
mixedCaseName MixedCaseName getMixedCaseName
name-with-dash NameWithDash getNameWithDash
aa_bb-cc AaBbCc getAaBbCc
Java Properties
Local schema components are mapped to:
Simple property )get, set)
String getName();
void setName(String value);
With customization: isSetName , unsetName
List property
In Java1.5:
[Link] getAddress(); List<AddressType>
Indexed property )next)
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"/>
Each item can be
some element or
List getAny();
value
)Simple Types )partial diagram
SimpleType
Primtive List Union Restriction
List Next (1)
Represented as
validation
ID/IDREF String/Object constraints
date Calendar
maxInclusive
integer BigInteger
Enumeration
int int 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>
Common supertype
Public interface Date { of )Integer, String)
Object getMonth(); is Object
void setMonth(Object);
}
Type SafeEnumeration
<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 System
Any
SimpleType finished ComplexType Represented as
a Java interface
SimpleContent ComplexContent *Sequence * Choice * All
*Extension Extension
Elements
Attributes
Restriction
abstract
*
The interface
use
default
nillable
minOccurs *
fixed maxOccurs
extends the base
type’s interface Represented as
( ) Next
* Java properties
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
<xs:complexType name=“InternationalPrice">
<xs:simpleContent>
<xs:extension base="xs:int">
<xs:attribute name="currency“ type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
interface InternationalPrice {
int getValue();
void setValue(int);
String getCurrency();
void setCurrency(String);
}
Complex Type:Aggregation
<xs:element name="A" type="xs:int"/>
<xs:complexType name="Foo"> <xs:complexType name="Foo">
<xs:sequence> <xs:sequence>
<xs:element ref="A"/> <xs:element ref="A"/>
<xs:sequence>
<xs:element ref="B"/> <xs:element ref="B"/>
<xs:element ref="C"/> <xs:element ref="C"/>
</xs:sequence>
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
interface Foo {
int getA(); void setA(int);
int getB(); void setB(int);
int getC(); void setC(int);
}
Complex Type: Mixed Content
<xs:complexType name=“LetterBody"
mixed="true">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
…
</xs:sequence> XML fragment
</xs:complexType> Dear Mr.<name>Robert Smith</name>, …
interface lb
LetterBody LetterBody {
= [Link]();
interface
List gcl Name extends Element {
= [Link]();
String
[Link]("Dear getValue();
Mr.");
void setValue(String);
[Link]([Link]("Robert Smith"));
}
… The list may contain
List getContent(); elements and strings
}
Complex Type:Choice
<xs:complexType name="FooBarType">
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:complexType>
Customization (Not implemented yet) public interface FooBarType {
int getFoo();
public interface FooBarType {
void setFoo(int value);
Object getFooOrBar();
String getBar();
void setFooOrBar(Object);
void setBar(String value);
}
boolean isSetFoo();
Common supertype of void unsetFoo();
)Integer, String) is boolean isSetBar();
Object void unsetBar();
Similar to union }
WhenmaxOccurs>1
<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>
public interface FooBarType {
interface Foo extends Element {…}
interface Bar extends Element {…}
// Items are instances of Foo and Bar
List getFooOrBar();
}
For a sequence: List getFooAndBar()
The programmer needs to make sure that
the 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):
unmarshal
XML
Objects
≠ in
memory
XML
marshal
Nillable elements
<xs:element name=“age" type=“xs:int" nillable="true"/>
Integer getAge();
void setAge(Integer value);
Java: setAge( new Integer(25) ) or setAge(null)
XML: <age>25</age> or <age xsi:nil="true"/>
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> [Link](5);
</xs:choice> [Link](“a”);
</xs:complexType>
What happens
when we marshal
public interface ABType { obj?
int getA(); void setA(int value);
String getB(); void setB(String value); 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.”
Question: What is the output ?
xs:choice between Foo and Bar
[Link](42);
[Link](42);
42 true
[Link]();
[Link]("A");
[Link](
[Link]( [Link]() );
[Link]() );
The END
Any questions?