Java Architecture for XML Binding (JAXB)

JAXB fournit une manière simple de lier un schéma XML à une représentation objet. Il facilite l'incorporation des données XML dans les applications basées sur la technologie Java sans avoir nécessairement des connaissances poussées en XML.

JAXB processus

Sans Jaxb, pour accéder et afficher les données d'un fichier XML, on utilise SAX ou DOM. Par exemple pour traiter le document XML books.xml une possibilité est d'utiliser SAX comme dans l'exemple ci-après SansJaxb.java. Le traitement devient vite long et fastidieux.

Avec JAXB pas besoin d'utiliser de parser (SAX ou DOM) ni d'écrire de méthodes d'accès au données XML (callback pour SAX). Une condition nécessaire par contre est que le fichier XML soit lié à un schéma XML. Avec Jaxb, le fichier XML est transformé en classes Java. Pour notre exemple, le schéma ressemble à books.xsd

Binding: Génération du Java à partir du schéma en ligne de commande

Aide en ligne

C:\java\jaxb\lib>java -jar jaxb-xjc.jar

-p indique le package de sortie
-d indique le répertoire de sortie
-extension pour l'utilisation de jaxb:globalBindings (avec -b)
-b fichier pour la customization

C:\jaxb\lib>java  -jar jaxb-xjc.jar -p ch.gm.gen -d C:\jaxb\test\gen\ -b C:\jaxb\test\custom.xml C:\jaxb\test\books.xsd -extension

compilation

C:\jaxb\test>javac -sourcepath .\gen -classpath C:\jaxb\lib\jaxb-api.jar -d bin gen/ch/gm/gen/*.java

Génération des beans avec/sans interface

JAXB 2.x par défaut crée des "plain Java beans", alors que la v.1.0 crée une interface séparée et son implementation.

Pour générer l'interface/l'implémentation ajouter le code suivant dans le fichier xml appelé avec l'option -b

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
	<globalBindings generateValueClass="false" />
</bindings>

Génération de classes Serializable

Pour générer des classe implémentant java.io.Serializable ajouter le code suivant dans le fichier xml de customisation. L'attribut uid permet de setter la valeur du serialVersionUID.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
	<globalBindings>
		<xjc:serializable uid="1" />
	</globalBindings>
</bindings>

Utilisation de java.util.Date au lieu de XMLGregorianCalendar

La classe XMLGregorianCalendar est plus précise que la classe java.util.Calendar mais par contre elle n'est pas Serializable. Pour utiliser java.util.Calendar, il faut ajouter le code suivant dans le fichier xml de customisation.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
	<globalBindings>
		<javaType name="java.util.Calendar" xmlType="xs:date"
			parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
			printMethod="javax.xml.bind.DatatypeConverter.printDate" />
	</globalBindings>
</bindings>

Création d'un fichier XML

A) Création du contenu

JAXB 1.0 requiert l'utilisation de ObjectFactory, par exemple: new ObjectFactory().createAbc(). Avec JAXB 2.0, on peut simplement faire new Abc(). De plus, l'exception JAXBExceptions n'est plus levée.

//Code JAXB 1.0

ObjectFactory objFactory = new ObjectFactory();

Collection collection = (Collection) objFactory.createCollection();

Collection.BooksType booksType = objFactory. createCollectionTypeBooksType();

List bookList = booksType.getBook();

BookType book = objFactory.createBookType();

book.setItemId("307");
book.setName("JAXB today and beyond");
book.setDescription("This is an intermediate book on JAXB");
book.setISBN(987665L);
book.setPrice("45$");
book.setPublicationDate(new GregorianCalendar(2000,2,2));
book.setBookCategory("other");

bookList.add(book);
collection.setBooks(booksType);

B) Transformation du contenu en XML (marshalling)

La transformation se fait au moyen d'un objet JAXBContext auquel il faut spécifier le(s) package(s) qui contiennent les classes et interfaces des schémas utilisés. Il est ainsi possible de construire un document XML combinant plusieurs éléments XML de différents schémas.

Création d'un fichier xml physique

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

JAXBContext jaxbContext = JAXBContext.newInstance("mon.package");

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));

marshaller.marshal(collection, new FileOutputStream("jaxbOutput.xml"));

Création d'un byte[]

JAXBContext jaxbContext = JAXBContext.newInstance(Envelope.class
                                                     .getPackage().getName()) ;

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, new Boolean(true));

//Encoding
marshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-8859-1") ;

//Ajout à l'élément racine de xsi:noNamespaceSchemaLocation="http://www.test.ch"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, 
                       "http://www.test.ch") ;

//Ajout à l'élément racine de xsi:schemaLocation="http://www.test.ch" 
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, 
                       "http://www.test.ch") ;

ByteArrayOutputStream byteArray = new ByteArrayOutputStream() ;

marshaller.marshal(envelope, byteArray) ;
    
return byteArray.toByteArray() ;

C) Validation

Il est possible de valider le contenu en utilisant l'objet Validator

import javax.xml.bind.Validator;

Validator validator = jaxbContext.createValidator();
validator.validate(collection);

Liens