RESTer simple avec Spring et JAXB – Partie 1 : Binding avec JAXB

Beaucoup de tutoriaux s'arrête à l'approche serveur de l'utilisation de REST. Le but de cette série de posts est d'écrire une application web utilisant le style d'architecture REST et de fournir une API cliente permettant d'utiliser les services offerts par le serveur.

Cette première partie a pour objectif de générer la représentation XML du modèle métier de l'exemple. Dans un second billet, l'approche serveur sera abordée. Le projet se terminera par l'écriture de la partie cliente de l'application.

Les choix suivants ont été faits :

  • l'application doit être la plus simple possible. Elle utilisera uniquement le JDK java 1.6 et le framework Spring.
  • les services offerts par le serveur doivent être accessible à tous les langages de programmation, d'où l'utilisation de REST et du XML.
  • l'API Java cliente ne doit pas obliger le développeur à utiliser des implémentations spécifiques du modèle. Le contrat partagé entre le client et le serveur ne devra donc faire référence qu'à des interfaces.
  • Le souhait a été fait de ne pas utiliser de DTO (Data transfer object), alourdissant le code avec des convertisseurs ou des frameworks spécifiques.

Cette première partie a pour objectif la génération de la représentation XML du modèle métier de l'exemple.
REST sera abordé dans les parties suivantes de ce tutorial.

JAXB (Java Architecture for XML Binding) a été intégré à la version 1.6 du JDK java. Cette API permet de générer du code à partir de schémas de données xml (fichiers .xsd). Nous allons l'utiliser d'une toute autre manière. Grâce à ses annotations, cette spécification permet de générer la représentation d'un objet au format xml, json...
L'exemple suivant utilise la représentation d'un modèle simple : un client. Toutes les sources sont jointes à ce billet.

ClientImpl.java :

@XmlRootElement(name = "customer")
public class ClientImpl implements Client
{

    @XmlElement(name = "reference")
    private String reference = "";
    
    @XmlElement(name = "firstName")
    private String prenom = "";
    
    @XmlElement(name = "name")
    private String nom = "";
    
    @XmlElement(name = "company")
    private String société = "";
    
    @XmlElement(name = "creationDate")
    @XmlJavaTypeAdapter(LocalDateXmlAdapter.class)
    private LocalDate dateCreation = new LocalDate();
    
    @XmlElementRef(name = "email", type = AdresseEmailImpl.class)
    @XmlElementWrapper(name = "emails")
    private List<AdresseEmail> adresseEmails = new ArrayList<AdresseEmail>();
	
	// + constructeur vide
	// + getters/setters
}

AdresseEmailImpl.java :

@XmlRootElement(name = "email")
public class AdresseEmailImpl implements AdresseEmail
{

    @XmlElement(name = "address")
    private String adresse = "";
    
    @XmlElement(name = "type")
    private TypeAdresseEmail type = TypeAdresseEmail.PERSONNEL;
	
    // + constructeur vide
    // + getters/setters
	
}

Le modèle est très simple mais reprend quelques petites subtilités à intégrer :

  • La gestion des listes,
  • La gestion d'une entité externe (LocalDate). J'utilise jodatime car il offre beaucoup plus de possibilités que Calendar ou Date,
  • La gestion des enums avec TypeAdresseEmail.

REMARQUE : nous pouvons constater que ce modèle dépend uniquement des classes du JDK 1.6 et de jodatime (optionnel).

Chaque @XmlElement est un noeud de l'arborescence XML.
@XmlRootElement représente le noeud racine.
@XmlElementRef définit une référence vers une entité complexe (intègre l'implémentation que l'on utilisera lors de la génération de l'objet à partir du XML).
@XmlElementWrapper permet d'englober la liste des adresses mails dans une balise portant le nom "emails" (voir la représentation ci-dessous).
@XmlJavaTypeAdapter permet de définir un adaptateur qui sera utilisé pour convertir l'attribut. Dans ce cas précis, nous convertissons l'objet localDate en une chaîne de caractère du type "aaaa-mm-jj".

Représentation XML recherchée :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
	<reference>001</reference>
	<firstName>prenom</firstName>
	<name>nom</name>
	<company>société</company>
	<creationDate/>
	<emails>
		<email>
			<address>nom@societe.com</address>
			<type>PROFESSIONNEL</type>
		</email>
		<email>
			<address>nom@perso.com</address>
			<type>PERSONNEL</type>
		</email>
	</emails>
</customer>

Un petit test permet de voir le flux XML généré. Ce test utilise Spring et son marshaller Jaxb2 inclus dans le module oxm :

        final ConfigurableApplicationContext contexte = new ClassPathXmlApplicationContext("test-context.xml");
        
        final Client client = (Client) contexte.getBean("client");
        final Marshaller marshaller = (Marshaller)contexte.getBean("xmlMarshaller");
        
        final ByteArrayOutputStream out =  new ByteArrayOutputStream();
        final StreamResult resultat = new StreamResult(out);
        marshaller.marshal(client, resultat);
        
        System.out.println(new String(out.toByteArray()));

Voici les beans Spring associés :

	<!-- Le marshaller Jaxb du module oxm -->
	<bean id="xmlMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
        <property name="classesToBeBound">
            <list>
                <value>com.netapsys.restsimple.modele.impl.AdresseEmailImpl</value>
                <value>com.netapsys.restsimple.modele.impl.ClientImpl</value>
            </list>
        </property>
    </bean>
    
    <!-- Bean client exemple -->
    <bean id="client" class="com.netapsys.restsimple.modele.impl.ClientImpl" scope="prototype">
    	<property name="reference" value="001"/>
    	<property name="prenom" value="prenom"/>
    	<property name="nom" value="nom"/>
    	<property name="societe" value="société"/>
    	<property name="adresseEmails">
    		<list>
    			<bean class="com.netapsys.restsimple.modele.impl.AdresseEmailImpl">
    				<property name="adresse" value="nom@societe.com"/>
    				<property name="type" value="PROFESSIONNEL" />
    			</bean>
    			<bean class="com.netapsys.restsimple.modele.impl.AdresseEmailImpl">
    				<property name="adresse" value="nom@perso.com"/>
    				<property name="type" value="PERSONNEL" />
    			</bean>
    		</list>
    	</property>
    </bean>

L'utilisation de JAXB permet de représenter très rapidement un objet en XML. Le marshaller de spring oxm nous sert uniquement pour ce test. Il ne sera plus utilisé par la suite.

Dans le billet suivant nous mettrons en place la partie serveur de l'application.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.