ИСПОЛЬЗОВАНИЕ ТЕХНОЛОГИИ ПРИ РАЗРАБОТКЕ ПРИЛОЖЕНИЙ JAXB

advertisement
CERN – European Organization for Nuclear Research
IT Department – e-Business Section
ИСПОЛЬЗОВАНИЕ ТЕХНОЛОГИИ JAXB
ПРИ РАЗРАБОТКЕ
XML ПРИЛОЖЕНИЙ
Afonin Alexey, Derek Mathieson
e-Business section, IT department
CERN – Geneva, Switzerland
JAXB
JAXB:
 The Java Architecture for XML Binding
 Спецификация принята 8 Января 2003 года
http://java.sun.com/xml/downloads/jaxb.html
Доступные реализации:
 SUN, является частью Java Web Services Developer Pack
http://java.sun.com/xml/downloads/jaxb.html
 Apache JAXME
http://ws.apache.org/jaxme/
Архитектура JAXB
Пример: XML
<orders-list>
<order>
<number>1001</number>
<date>2005-01-01</date>
<description>First Order</description>
<amount>10</amount>
</order>
<order>
<number>1002</number>
<date>2005-01-02</date>
<description>Second Order</description>
<amount>20.2</amount>
</order>
</orders-list>
Пример: XML Schema
<xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsd:element name="orders-list">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="order" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="order">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="number" type="xsd:long"/>
<xsd:element name="date" type="xsd:date"/>
<xsd:element name="description" type="xsd:string"/>
<xsd:element name="amount" type="xsd:double"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Пример: Генерация Java классов
Из командной строки:
%jwsdp.home%\jaxb\bin\xjc.bat
-p generated -d src simple-order.xsd
Из скрипта Ant:
<project basedir="." default="generate">
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask“
classpathref="classpath“>
<target name="generate">
<xjc schema="simple-order.xsd"
target="src"
package="generated"/>
</target>
</project>
Пример: сгенерированные Java классы
OrdersListType.java
public interface OrdersListType {
java.util.List getOrder();
}
OrderType.java
public interface OrderType {
double getAmount();
void setAmount(double value);
java.lang.String getDescription();
void setDescription(java.lang.String value);
java.util.Calendar getDate();
void setDate(java.util.Calendar value);
long getNumber();
void setNumber(long value);
}
Пример: работа с JAXB
Чтение из XML файла
JAXBContext jaxbCtx = JAXBContext.newInstance("generated");
Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
OrdersListType orders
= (OrdersListType)unmarshaller.unmarshal(
new File("simple-order.xml"));
List ordersList = orders.getOrder();
for (int i = 0; i < ordersList.size(); i++) {
OrderType order = (OrderType)ordersList.get(i);
System.out.println("Number = " + order.getNumber()
+ ", amount = " + order.getAmount());
}
...
Пример: работа с JAXB
Изменение XML файла
...
ObjectFactory objectFactory = new ObjectFactory();
Order newOrder = objectFactory.createOrder();
newOrder.setNumber(2006);
newOrder.setDate(Calendar.getInstance());
newOrder.setDescription("New Order");
newOrder.setAmount(100);
orders.getOrder().add(newOrder);
Marshaller marshaller = jaxbCtx.createMarshaller();
marshaller.marshal(orders,
new FileOutputStream(new File("simple-order.xml")));
Пакет Связывания
Binding Framework
Пакет Связывания
Основные операции:
 маршаллинг (marshalling)
 демаршаллинг (unmarshalling)
 проверка (validation)
Класс javax.xml.bind.JAXBContext - "точка входа" в JAXB API
public abstract class JAXBContext {
static JAXBContext newInstance(String contextPath)
static JAXBContext newInstance(String contextPath,
ClassLoader contextPathCL)
abstract Unmarshaller createUnmarshaller();
abstract Marshaller createMarshaller();
abstract Validator createValidator();
}
Проверка XML документа
JAXB предоставляет три варианта проверки XML документа:
 во время демаршаллинга (unmarshall-time validation)
 по требованию (on-demand validation)
 "на лету" (fail-fast validation)
Validator позволяет проверять объектное представление документа
public interface Validator {
ValidationEventHandler getEventHandler()
void setEventHandler(ValidationEventHandler handler)
boolean validate(java.lang.Object subrootObject)
boolean validateRoot(java.lang.Object rootObject)
}
Демаршаллинг
Unmarshaller читает XML документ, выполняет его проверку и
строит объектную модель
public interface Unmarshaller {
boolean isValidating() throws JAXBException;
void setValidating(boolean b) throws JAXBException;
ValidationEventHandler getEventHandler()
throws JAXBException;
void setEventHandler(ValidationEventHandler handler)
throws JAXBException;
Object
Object
Object
Object
Object
Object
}
unmarshal(File file) throws JAXBException;
unmarshal(InputStream is) throws JAXBException;
unmarshal(URL url) throws JAXBException;
unmarshal(Source source) throws JAXBException;
unmarshal(Node node) throws JAXBException;
unmarshal(InputSource is) throws JAXBException;
Маршаллинг
Marshaller сохраняет объектную модель в XML документ
public interface Marshaller {
ValidationEventHandler getEventHandler() throws JAXBException;
void setEventHandler(ValidationEventHandler handler)
throws JAXBException;
void
void
void
void
void
Node
marshal(Object
marshal(Object
marshal(Object
marshal(Object
marshal(Object
getNode(Object
o,
o,
o,
o,
o,
o)
OutputStream os) throws JAXBException;
Writer writer) throws JAXBException;
Result result) throws JAXBException;
Node node) throws JAXBException;
ContentHandler ch) throws JAXBException;
throws JAXBException;
Object getProperty(String s) throws PropertyException;
void setProperty(String s, Object o) throws PropertyException;
String JAXB_ENCODING = "jaxb.encoding";
String JAXB_FORMATTED_OUTPUT = "jaxb.formatted.output";
}
Связывание XML схемы
и Java Представления
Binding XML Schema to Java Classes
Связывание имен: XML  Java
XML Имя
Имя Класса
Имя Метода
Имя Константы
MixedCaseName
getMixedCaseName
MIXED_CASE_NAME
Answer42
getAnswer42
ANSWER_42
name-with-dashes
NameWithDashes
getNameWithDashes
NAME_WITH_DASHES
other_punct-chars
OtherPunctChars
getOtherPunctChars
OTHER_PUNCT_CHARS
mixedCaseName
Answer42
Связывание составных типов данных
Составной тип XML схемы  Java интерфейс
<xsd:complexType name="personType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="departmentId" type="xsd:long"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:long"/>
</xsd:complexType>
public interface PersonType
{
long getDepartmentId();
void setDepartmentId(long value);
java.lang.String getName();
void setName(java.lang.String value);
long getId();
void setId(long value);
}
Свойства (Properties)
Вложенные компоненты XML схемы  Java свойства
Простое свойство (Simple Property)
<xsd:element name="name" type="xsd:string"/>
java.lang.String getName();
void setName(java.lang.String value);
Группа свойств (Collection Property)
<xsd:element name="item" type="xsd:string"
maxOccurs="unbounded"/>
java.util.List getItem();
Перечисление (Type Safe Enumeration)
Производный атомарный тип данных с ограничением типа
«перечисление»  Перечисление (Type Safe Enumeration)
<xsd:simpleType name="countryType">
<xsd:restriction base="xsd:NCName">
<xsd:enumeration value="FRANCE"/>
<xsd:enumeration value="SWITZERLAND"/>
</xsd:restriction>
</xsd:simpleType>
public class CountryType {
private final String value;
protected CountryType(String v) { value = v; }
public final static CountryType FRANCE
= new CountryType("FRANCE");
public final static CountryType SWITZERLAND
= new generated.CountryType("SWITZERLAND");
...
}
Связывание встроенных типов данных
Таблица соответствия встроенных типов
(Simple Built-in Types)
Тип данных XML схемы
Тип данных Java
xsd:string
java.lang.String
xsd:integer
java.math.BigInteger
xsd:int
int
xsd:long
long
xsd:decimal
java.math.BigDecimal
xsd:float
float
xsd:double
double
xsd:boolean
boolean
xsd:byte
byte
xsd:dateTime
java.util.Calendar
xsd:anySimpleType
java.lang.String
Наследование
Наследование XML типов через ограничение (restriction) или
расширение (extension)  Java наследование
<xsd:complexType name="Address">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:complexContent>
<xsd:extension base="Address">
<xsd:sequence>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:integer"/>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Наследование
Наследование XML типов через ограничение (restriction) или
расширение (extension)  Java наследование
public interface Address
{
java.lang.String getCity();
void setCity(java.lang.String value);
java.lang.String getStreet();
void setStreet(java.lang.String value);
java.lang.String getName();
void setName(java.lang.String value);
}
public interface USAddress extends Address
{
java.lang.String getState();
void setState(java.lang.String value);
long getZip();
void setZip(long value);
}
Переопределение Связывания
Customizing JAXB Bindings
Зачем Переопределять?
Стандартное связывания (Default Binding)
Переопределение связывания:
 создание документации (Javadoc)
 изменение правил именования
 разрешить конфликтов имен
 определить имена для констант перечислений
 определять свои типы данных для атрибутов
 переопределять связывание встроенных типов
 переопределять маршаллинг / демаршаллинг для
пользовательских типов данных
Встроенное и Внешнее Переопределение
Встроенное переопределение – внутри XML схемы
<xs:annotation>
<xs:appinfo>
<!-- binding declarations -->
</xs:appinfo>
</xs:annotation>
Внешнее переопределение – отдельный файл
<jxb:bindings schemaLocation = "xs:anyURI">
<jxb:bindings node = "xs:string">*
<!-- binding declarations -->
<jxb:bindings>
</jxb:bindings>
Использование Внешнего Переопределения
Командная строка
xjc –b <file> <schema>
Скрипт Ant
<xjc schema="simple-order.xsd"
target="src"
binding="cxml-binding.xjb"
package="generated"/>
Глобальные Переопределения
<globalBindings>
[ collectionType = "collectionType" ]
[ generateIsSetMethod= "true" | "false" | "1" | "0" ]
[ enableFailFastCheck = "true" | "false" | "1" | "0" ]
[ underscoreBinding = "asWordSeparator" | "asCharInWord" ]
[ typesafeEnumBase = "typesafeEnumBase" ]
[ <javaType> ... </javaType> ]*
</globalBindings>
Переопределения Уровня Схемы
<schemaBindings>
[ <package> package </package> ]
[ <nameXmlTransform> ... </nameXmlTransform> ]*
</schemaBindings>
<package [ name = "packageName" ]
[ <javadoc> ... </javadoc> ]
</package>
<nameXmlTransform>
[ <typeName [ suffix="suffix" ]
[ prefix="prefix" ] /> ]
[ <elementName [ suffix="suffix" ]
[ prefix="prefix" ] /> ]
</nameXmlTransform>
Переопределения Типов Данных и Компонент
Связывание Классов
<class [ name = "className"]
[ implClass= "implClass" ] >
[ <javadoc> ... </javadoc> ]
</class>
Связывание Свойств
<property[ name = "propertyName"]
[ collectionType = "propertyCollectionType" ]
[ generateIsSetMethod = "true" | "false" | "1" | "0" ]
[ enableFailFastCheck ="true" | "false" | "1" | "0" ]
[ <baseType> ... </baseType> ]
[ <javadoc> ... </javadoc> ]
</property>
<baseType>
<javaType> ... </javaType>
</baseType>
Переопределения Типов Данных и Компонент
Преобразование типов данных Java  XML
<javaType name= "javaType"
[ xmlType= "xmlType" ]
[ parseMethod= "parseMethod" ]
[ printMethod= "printMethod" ]/>
Пример Настройки Связывания
<jxb:bindings
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="1.0">
<jxb:bindings schemaLocation="cxml.xsd" node="/xs:schema" >
<jxb:schemaBindings>
<jxb:package name="cern.edh.cxml.objects"/>
<jxb:nameXmlTransform>
<jxb:typeName suffix="Type"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
...
Пример Настройки Связывания
<jxb:bindings node="/xs:schema" schemaLocation="cxml.xsd">
...
<jxb:bindings node="//xs:simpleType[@name='datetime.tz']">
<jxb:javaType name="java.util.Date"
parseMethod="cern.edh.cxml.DateConverter.parseDateTz"
printMethod="cern.edh.cxml.DateConverter.printDateTz"/>
</jxb:bindings>
<jxb:bindings node="//xs:simpleType[@name='deploymentModeValue']">
<jxb:typesafeEnumClass/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Пример: Разрешение Конфликтов Имен
<xs:element name="Money" type="Money"/>
<xs:complexType name="Money">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="currency" type="xs:string"/>
<xs:attribute name="alternateAmount" type="xs:double"/>
<xs:attribute name="alternateCurrency" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
cern.edh.cxml.objects.Money
cern.edh.cxml.objects.MoneyType
<jxb:nameXmlTransform>
<jxb:typeName suffix="Type"/>
</jxb:nameXmlTransform>
Пример: Преобразование Типов Данных
<jxb:bindings node="//xs:simpleType[@name='datetime.tz']">
<jxb:javaType name="java.util.Date"
parseMethod="cern.edh.cxml.DateConverter.parseDateTz"
printMethod="cern.edh.cxml.DateConverter.printDateTz"/>
</jxb:bindings>
package cern.edh.cxml;
public class DateConverter
{
public static java.util.Date parseDateTz(String lexicalDate)
throws ParseException {...}
public static String printDateTz(java.util.Date date) {...}
}
Пример: Преобразование Типов Данных
<xs:simpleType name="datetime.tz">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:element name="cXML">
...
<xs:attribute name="timestamp" type="datetime.tz"/>
<xs:element name="cXML">
public interface CXMLType
{ ...
java.util.Date getTimestamp();
void setTimestamp(java.util.Date value);
}
<cXML timestamp="2000-08-03T08:49:09+07:00">
...
</cXML>
Пример: Перечисление
<jxb:bindings node="//xs:simpleType[@name='deploymentModeValue']">
<jxb:typesafeEnumClass/>
</jxb:bindings>
<xs:simpleType name="deploymentModeValue">
<xs:restriction base="xs:sting">
<xs:enumeration value="production"/>
<xs:enumeration value="test"/>
</xs:restriction>
</xs:simpleType>
public class DeploymentModeValue {
public final static DeploymentModeValue PRODUCTION
= new DeploymentModeValue(_PRODUCTION);
public final static DeploymentModeValue TEST
= new DeploymentModeValue(_TEST);
...
}
JAXB vs. JAXP
JAXB следует использовать когда нужно:
 Создавать объектные представления данных XML
 Обрабатывать только верные данные
 Преобразовывать данные к различным типам
JAXP следует использовать когда нужно:
 Обрабатывать документы, построенные на различных DTD
 Обрабатывать документы, которые не обязательно являются
правильными
 Применять XSLT преобразования
 Обрабатывать лишь отдельные части XML документа
Использование JAXB
Система Электронного Документооборота (EDH)
Приложение электронной коммерции B2B:
 стандарт cXML
 ~ 100 интерфейсов объектной модели
 ~ 100 классов реализации
Спасибо за внимание!

XML элемент
XML элемент  Java интерфейс элемента
Тип элемента объявлен составным (Complex type definition):
<xsd:complexType name="personType">
... <!-– вложенные элементы -->
</xsd:complexType>
<xsd:element name="person" type="personType"/>
public interface PersonType
{ ... <!– свойства для вложенных элементов -->
}
public interface Person
extends javax.xml.bind.Element, PersonType
{
}
XML элемент
XML элемент  Java интерфейс элемента
Тип элемента объявлен простым (Simple type definition):
<xsd:element name="name" type="xsd:string"/>
public interface Name
extends javax.xml.bind.Element
{
java.lang.String getValue();
void setValue(java.lang.String value);
}
Уровни Действия Переопределения
Компонент
Тип Данных
Схема
Глобальные Переопределения
Каждый следующий уровень по отношению к предыдущему:
 наследует
 переопределяет
Download