Recevez les mises à jour gratuites du blog par Email : »» Garanti sans spam indésirable ««

Dozer : Utilisation avancée des Convertisseurs

de Mimie le 5 mai 2010

Rubrique : Programmation

Introduction

Je vous avais présenté il y a quelques temps Dozer et son utilisation générale, aujourd’hui je vais vous présenter la façon dont j’utilise les « converter » (ou convertisseurs) spécifiques à cet outil de copie d’objets Java.

© http://image.made-in-china.com

© http://image.made-in-china.com

Les convertisseurs sont utilisés pour améliorer le mapping entre les objets à copier : lorsque dans le fichier de configuration XML de Dozer une classe A contient un attribut d’une classe B et qu’un convertisseur est nommé pour effectuer cette transformation alors c’est celui-ci qui est utilisé et non le le mapping de base de Dozer.

Utilisation standard

Lorsque le mapping entre deux classes est un peu complexe ou que Dozer, par défaut, ne permet pas de faire ce que l’on souhaite, alors les convertisseurs sont très utiles et efficaces.

Prenons un exemple simple : vous voulez convertir un objet de type java.lang.Boolean en java.lang.String et que le la valeur TRUE du premier devienne un « YES » et que la valeur FALSE un « NO » (et vice versa), voici comment procéder :

  • Fichier de configuration XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<!-- Dozzer mapper -->
	<bean id="dozerMapper" class="org.dozer.DozerBeanMapper">
		<description>Dozer Mapper with mapping files and custom converters</description>
		<property name="mappingFiles">
			<list>
				<value>desgeeks-dozer-config.xml</value>
			</list>
		</property>
		<property name="customConvertersWithId">
			<map>
				<entry key="booleanConverterId" value-ref="booleanConverter" />
			</map>
		</property>
	</bean>
	<!-- custom converter -->
	<bean id="booleanConverter" class="fr.mtg.unit.presentation.converter.BooleanConverter">
		<description>Converter to convert Boolean to String (TRUE <=> "YES", FALSE <=> "NO")</description>
	</bean>
</beans>
  • Fichier de mapping (desgeeks-dozer-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd">
         <!-- ClassA to ClassB -->
  	<mapping>
    	<class-a>votre.package.de.class.ClassA</class-a>
    	<class-b>votre.package.de.class.ClassB</class-b>
    	<field>
      		<a>id</a>
      		<b>identifiant</b>
    	</field>
    	<field custom-converter-id="booleanConverterId">
    		<a>authorized</a>
    		<b>estAutorise</b>
    	</field>
  	</mapping>
</mappings>
  • Convertisseur Java
import org.dozer.DozerConverter;
public class BooleanConverter extends DozerConverter<Boolean, String> {
	public BooleanConverter() {
		super(Boolean.class, String.class);
	}
	@Override
	public Boolean convertFrom(String paramB, Boolean paramA) {
		if ("YES".equalsIgnoreCase(paramB)) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}
	@Override
	public String convertTo(Boolean paramA, String paramB) {
		if (paramA != null && paramA.equals(Boolean.TRUE)) {
			return "YES";
		}
		return "NO";
	}
}

Utilisation avancée

Etant donné que lorsqu’un convertisseur est nommé dans le fichier de mapping de Dozer c’est celui-ci qui est utilisé et plus le mapping de base pour la copie des attributs, cela veut dire que nous devons refaire le mapping pour chaque champ de notre objet à l’intérieur même du convertisseur.

Voici la solution que j’utilise pour s’affranchir du mapping « basique » afin de s’occuper, dans mes convertisseurs, uniquement des traitements spécifiques que Dozer ne peut faire naturellement.

Pour cela j’injecte le bean Spring dozerMapper dans mes bean ‘converter’ pour que les méthodes « convertTo » et « convertFrom » puissent appeler le mapping standard de Dozer avant d’effectuer des conversions spécifiques :

        @Override
	public CardRemote convertTo(Card paramA, CardRemote paramB) {
		// dozer standard mapping
		CardRemote cardRemote = (CardRemote) mapper.map(paramA, CardRemote.class);
		// card images
		cardRemote.setImageNormal(ImageUtil.getSourceImageCard(paramA, ImageUtil.CARD_IMAGE_NORMAL));
		cardRemote.setImageBig(ImageUtil.getSourceImageCard(paramA, ImageUtil.CARD_IMAGE_BIG));
		cardRemote.setManaCostAsImage(ImageUtil.replaceSymbolCodeBySourceImage(paramA.getManaCost()));
		cardRemote.setTextAsImage(ImageUtil.replaceSymbolCodeBySourceImage(paramA.getText()));
		return cardRemote;
	}

Cela permet d’appeler en premier la copie de l’objet Card vers CardRemote par le biais du mapping Dozer :

        <!-- Card to CardRemote -->
  	<mapping>
    	<class-a>fr.mtg.unit.domain.model.Card</class-a>
    	<class-b>fr.mtg.unit.presentation.remote.CardRemote</class-b>
    	<field>
      		<a>pkCard</a>
      		<b>id</b>
    	</field>
    	<field>
      		<a>manaCost</a>
      		<b>manaCostAsText</b>
    	</field>
    	<field>
      		<a>text</a>
      		<b>textAsText</b>
    	</field>
    	<field>
      		<a>cardLink.englishCard</a>
      		<b>englishCardId</b>
    	</field>
    	<field>
      		<a>cardLink.frenchCard</a>
      		<b>frenchCardId</b>
    	</field>
    	<field custom-converter-id="setConverterId">
    		<a>set</a>
    		<b>set</b>
    	</field>
  	</mapping>

puis d’effectuer des traitements spécifiques de conversion de l’objet Card vers CardRemote.

Pour le convertisseur « setConvertId » nommé dans ci-dessus, je procède de la même façon pour que tout se fasse tout seul

Conclusion

L’avantage de la seconde solution est qu’à présent vous pouvez utiliser directement vos classes « converter » dans vos propres classes utilitaires car ceux-ci comprennent déjà le mapping de Dozer qui est appelé implicitement dans vos méthodes « convertTo » et « convertFrom ».

Je ne sais pas si beaucoup d’entre vous utilisent Dozer dans vos architectures distribuées mais pour ma part c’est un « must have », à vous de tester !

Cet article a été écrit par :

– qui a déjà rédigé 123 posts sur Des Geeks et des lettres.

Passionné d'informatique et développeur JavaEE de métier, je me consacre principalement à écrire des billets sur les sujets du Web et de la programmation Web. Ce blog est un espace qui me permet de partager mes découvertes avec vous et me sert accessoirement de pense bête !

Contacter l'auteur

Jetez aussi un oeil sur :

{ 2 commentaires… à vous de vous exprimer ! }

1 Greg mai 5, 2010 à 13 h 17 min

« Mais à quoi ça sert de transvaser les données de mon objet vers un autre ? » Nan je rigole, tu donnes la réponse à cette question dans ton premier article ici :D

Répondre

2 Mimie mai 5, 2010 à 13 h 24 min

Klr, il est chouette cet outil, j’ai déjà converti mes collègues de bureau à l’utiliser dans leur projet perso :D ^^

Répondre

Laissez un Commentaire

Article précédent:

Article suivant: