添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

logo-java-performance Ce billet a pour origine un commentaire posté dans mon précédent billet et dans lequel Laurent demandait un retour d’expérience sur l’utilisation de frameworks Java de mapping objet vers objet tels Dozer ou ModelMapper .

Dans l’architecture d’une applicative n-tiers , une couche de mapping objet / objet peut intervenir à plusieurs niveaux :

  • En entrée ou en sortie d’un web service SOAP afin de convertir en objet métier les DTO générés à partir du WSDL, ou inversement.
  • Entre la couche de présentation et la couche de services métiers lorsque la première expose des DTO et la seconde travaille avec des objets métiers.
  • Entre la couche de services métiers et la couche d’accès aux données afin de mapper les entités persistances en objets métiers.
  • Dans le premier exemple, le développeur n’a guère le choix. Dans les 2 autres, il s’agit d’un choix d’architecture.
    L’introduction d’une couche de mapping n’est pas un choix à prendre à la légère : ayant pour objectif de découpler les couches, elle complexifie l’application et peut détériorer ses performances. Le choix d’en introduire une et d’utiliser un framework pour faciliter sa mise en œuvre n’est pas non plus évident.

    Ce billet est découpé en 2 parties :

  • Une première dressant les avantages et les inconvénients d’utiliser Dozer par rapport à une approche manuelle ,
  • et une seconde présentant les résultats d’un micro-benchmark comparant plusieurs frameworks : Dozer , Orika , Selma , MapStruct et ModelMapper .
  • Tableau comparatif Dozer vs mapping manuel en Java

    Extrait d’un retour d’expérience , le tableau ci-dessous dresse les avantages et les inconvénients de Dozer par rapport à une approche manuelle. A vous de pondérer chaque avantage / inconvénient en fonction de vos exigences.

  • Lisibilité du XML pour mapper les champs : profondeur du chemin de la propriété, découplage entre la correspondance source/destination et la règle de transformation, conversion implicite en fonction des types source et destination
  • Réutilisation du code : transformations réutilisables
  • Structure le développement de mappings
  • Le mapping sert à la fois pour créer un nouvel objet et compléter un objet existant
  • Mapping bi-directionnel offert
  • Faibles performances
  • Mapping non compilé : pas de complétion dans l’IDE, refactoring  nécessitant des recherches dans le XML
  • Utilisation de converter pour gérer les cas compliqués (et ne pas faire appel à du code Java après le mapping Dozer).
  • Apprentissage du framework et des bonnes pratiques
  • En fonction de votre expertise, ce tableau pourrait être adapter avec d’autres frameworks.

    Quelque soit l’approche choisie (framework ou code manuel), seuls des tests unitaires permettront de valider le mapping. Ne pouvant être automatisés, ces tests s’avèrent malheureusement longs et fastidieux.

    Micro-benchmark

    Ne trouvant aucun comparatif récent sur les performances des frameworks de mapping, j’ai créé sur GitHub le projet java-object-mapper-benchmark . Ce dernier utilise JMH (Java Microbenchmarking Harness) pour réaliser un micro-benchmark entre Dozer, Selma, ModelMapper, Orika, MapStruct et un mapping écrit manuellement.

    Le diagramme ci-dessous présente résultats obtenus avec la configuration suivante :

  • OS: MacOSX
  • CPU: Core i7 2.8GHz 6MB cache × 4 cores
  • RAM: 16GB
  • JVM: Oracle 1.8.0_25 64 bits
  • Comme on pouvait s’y attendre, les performances du code écrit à la main sont les meilleures.
    Selma et MapStruct se rapprochent le plus des performances d’un code écrit manuellement. Ce résultat s’explique par le fait qu’ils génèrent le code source à l’aide de l’ Annotation Processor introduit par Java 6 (JSR-269).
    Basés sur l’ introspection de code, Dozer et ModelMapper sont peu performants.
    Entre ces 2 catégories, on retrouve Orika qui utilise au runtime l’API Java Compiler pour générer le code du mapping.

    Pour exécuter vous même le benchmark, Maven, un JDK et 3 lignes de commandes suffisent :

    git clone git://github.com/arey/java-object-mapper-benchmark.git 
    mvn clean install 
    java -jar target/benchmarks.jar

    Conclusion

    En 2015, l’utilisation d’un framework de mapping objet / objet basé sur la génération de code plutôt que sur l’introspection semble préférable. Non seulement les performances sont bien meilleures, mais le couplage avec le framework est faible puisqu’il est possible de le supprimer et de conserver dans votre SCM le code généré. Selma et MapStruct sont les 2 gagnants du benchmark.

    Encore une fois, avant de partir sur une telle approche, prenez un temps de réflexion. Des entités métiers annotées avec Bean Validation et traversant l’ensemble des couches restent l’architecture la plus simple à mettre en œuvre. Je suis déjà intervenu sur une application où une couche de mapping avait été mise en œuvre dès le départ pour des raisons de découplage, puis retirée au fur et à mesure car sa plus value était trop faible.

    Références :

  • Dozer vs Orika vs Manual (2013)
  • Java Bean Mapper Performance Tests (2007)
  • Selma, le mapping Java à la compilation (2014)
  • Using JMH for Java Microbenchmarking (2013)
  •