reseau social

La copie d'objets Java simplifiée avec Dozer

Un article de ToutProgrammer.com.

Sommaire

[modifier] Introduction

Souvent, lors du développement d'applications propres (respectant les couches) et plus particulièrement lorsque vos applications utilisent des DAO ou des SOA, vous devez cloisonner les beans utilisés dans celles-ci. Par exemple, les beans utilisés par le mapping de base de données ne doivent pas être utilisés pour les services métier. Ceci évite en cas de changement des objets de mapping de base de données d'impacter systématiquement les objets utilisés dans les services métier.

Dozer est un framework Java open source permettant la copie d'une grappe d'objets vers une autre grappe d'objets récursivement. Dozer offre certains mécanismes pour automatiser au plus la recopie des objets ayant les mêmes attributs.

[modifier] Téléchargement et installation

Le site officiel de Dozer est http://dozer.sourceforge.net/ et vous pouvez télécharger les ressources à partir du lien suivant: téléchargement de Dozer.

L'archive de Dozer est fournit sous la forme d'un .zip ou d'un .tar.gz et porte un nom du type dozer-2.4-src.zip. Dans celle-ci, on y trouve les sources, le JAR de Dozer (dans ce cas dozer-2.4.jar), le javadoc, ainsi que la documentation en format HTML et PDF. Egalement téléchargeable sur le site, un .jar avec toutes les dépendances nécessaires au bon fonctionnement de Dozer. Ce JAR porte un nom du type dozer-full-2.4.jar.

Si vous souhaitez gagner du temps pour vos tests, vous pouvez utiliser les JAR (dozer-2.4.jar et dozer-full-2.4.jar) dans le classpath de votre application. Si vous souhaitez faire les choses plus proprement, vous trouverez dans le répertoire dozer/repository de l'archive des sources dozer-2.4-src.zip tous les JAR des différentes dépendances (log4j, spring, ...).

[modifier] Mise en œuvre

Dans cette mise en oeuvre, nous n'utiliserons pas de framework IoC (Inversion of Control) mais uniquement Dozer avec l'usine qu'il propose.

[modifier] Cas simple

Dans le cas d'une utilisation la plus simple soit-il, Dozer s'utilise en 2 lignes comme ceci:

  1. MapperIF mapper = DozerBeanMapperSingletonWrapper.getInstance();
  2. UserB userB = (UserB)mapper.map(userA, UserB.class);

Dans ce cas, Dozer recopie les attributs de l'instance userA(une instance d'une objet UserA) vers une instance userBde type UserB. Pour arriver à ses fins, Dozer utilise la réflexion afin de déterminer les attributs à recopier et ou les recopier. Les objets UserAet UserB sont simples puisque les attributs portent les mêmes noms dans chacun des objets.

[modifier] Cas d'attributs nommés différemment

Les choses deviennent plus compliquées lorsqu'il faut recopier des objets avec des attributs différents.

En effet, Dozer n'est pas magique. Lorsque les attributs portent des noms différents, Dozer demande l'utilisation d'un fichier de mapping dont la syntaxe est très simple. Voici un exemple de fichier de mapping:

  1. <mappings>
  2. <mapping>
  3. <class-a>test.dozer.beans.source.AddressA</class-a>
  4. <class-b>test.dozer.beans.destination.AddressB</class-b>
  5. <field>
  6. <a>email</a>
  7. <b>emailAddress</b>
  8. </field>
  9. </mapping>
  10. </mappings>

Nous avons dans ce cas 2 classes (AddressA et AddressB). Dans la classe AddressB, l'attribut contenant l'adresse courriel se nomme emailAddressalors que dans l'objet AddressAle même attribut se nomme email. Le mapping est bi-directionnel, c'est-à-dire qu'il n'est pas nécessaire d'indiquer à la fois le mapping pour recopier le contenu de l'objet A dans l'objet B et le mapping pour copier l'objet B dans l'objet A.

Il est possible d'utiliser autant de fichiers de mapping que désiré. Une DTD est fournie avec Dozer pour aider le développeur lors de la réalisation de ces fichiers de mapping. Cette DTD est également accessible sur le web à l'adresse suivante: http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd

Enfin, pour utiliser les fichiers de mapping, il suffit de les déclarer à Dozer comme ceci (exemple en Java 5):

  1. // Définition des fichiers de mapping
  2. List<String> mappingFiles = new ArrayList<String>();
  3. mappingFiles.add("mappings/TestDozer03.xml");
  4. // Déclaration des fichiers de mapping
  5. DozerBeanMapper mapper = (DozerBeanMapper)DozerBeanMapperSingletonWrapper.getInstance();
  6. mapper.setMappingFiles(mappingFiles);

Bien entendu, on ajoute autant de fichiers de mapping que voulu dans la liste, la seule contrainte étant que ceux-ci doivent être présents dans le classpath.

[modifier] Paramétrages divers

[modifier] Conversion des dates en chaînes

Dans certains cas, vous pouvez avoir besoin de convertir une chaine en date et réciproquement. Ceci se fait par l'intermédiaire du fichier de mapping en précisant le format de la date (sur l'attribut de chaine) comme ceci:

  1. <field>
  2. <a date-format="MM/dd/yyyy HH:mm:ss:SS">dateString</a>
  3. <b>dateObject</b>
  4. </field>

Bien entendu, l'attribut date-format doit correspondre au format de la date tel qu'il apparait dans la chaine.

[modifier] Recopie de sous attributs

Dans ce cas, il est possible que vous ayez des attributs qui proviennent de différents objets d'une grappe. Prenons le cas d'une grappe qui dont les objets contiennent le nom, le prénom et l'adresse email de l'utilisateur. Vous pouvez alors écrire ceci dans le fichier de mapping:

  1. <mapping>
  2. <class-a>test.dozer.beans.source.MemberA</class-a>
  3. <class-b>test.dozer.beans.destination.Person</class-b>
  4. <field>
  5. <a>user.firstname</a>
  6. <b>firstname</b>
  7. </field>
  8. <field>
  9. <a>user.lastname</a>
  10. <b>lastname</b>
  11. </field>
  12. <field>
  13. <a>address.email</a>
  14. <b>email</b>
  15. </field>
  16. </mapping>

[modifier] Conclusion

Dozer est un outil puissant qui demande une certaine expertise car les paramétrages sont très nombreux. Mais il permettra de gagner sur le long terme un temps précieux en externalisant dans un fichier de mapping les relations qui existent entre les objets.