table of contents - github pages · getting started downloading the distribution if you are using...

96
1.1 1.2 1.3 1.3.1 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 3.1 3.2 3.3 3.4 3.5 4.1 4.2 4.3 Table of Contents Introduction Why Map? Getting Started Usage Mappings via XML via Annotations via API Configuration Configuration via XML Configuration via API Dozer mapping concepts Mapping Classes Basic Property Mapping Inheritance Mapping Context Based Mapping One-Way Mapping Copying By Object Reference Deep Property Mapping Indexed Property Mapping Excluding Fields Assembler Pattern Mapping immutable types How do i map a type of…? Enums String to Date Collections and Arrays Map Backed Property Mapping Proxy Objects What if i need to customise the mapping? Custom Converters Custom Bean Factories Custom Create Methods 1

Upload: others

Post on 30-May-2020

26 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

1.1

1.2

1.3

1.3.1

1.4

1.4.1

1.4.2

1.5

1.5.1

1.5.2

2.1

2.2

2.3

2.4

2.5

2.6

2.7

2.8

2.9

2.10

2.11

3.1

3.2

3.3

3.4

3.5

4.1

4.2

4.3

TableofContentsIntroduction

WhyMap?

GettingStarted

Usage

MappingsviaXML

viaAnnotations

viaAPI

Configuration

ConfigurationviaXML

ConfigurationviaAPI

DozermappingconceptsMappingClasses

BasicPropertyMapping

InheritanceMapping

ContextBasedMapping

One-WayMapping

CopyingByObjectReference

DeepPropertyMapping

IndexedPropertyMapping

ExcludingFields

AssemblerPattern

Mappingimmutabletypes

Howdoimapatypeof…?Enums

StringtoDate

CollectionsandArrays

MapBackedPropertyMapping

ProxyObjects

Whatifineedtocustomisethemapping?CustomConverters

CustomBeanFactories

CustomCreateMethods

1

Page 2: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

4.4

4.5

5.1

5.2

5.3

6.1

6.2

6.3

7.1

7.2

8.1

8.2

8.3

8.4

9.1

9.2

9.3

10.1

10.2

10.2.1

10.2.2

Customget()set()Methods

ExpressionLanguage

ExtraLogging

EventListening

MetadataQueryInterface

3rdPartySpringIntegration

SpringBootIntegration

JAXB

OtherFAQ

Examples

Migrationv5tov6

v6.0.0tov6.1.0

v6.1.0tov6.2.0

v6.2.0tov6.3.0

SchemaMappingXSD

Spring4XSD

User’sGuidePDF

EclipsePluginInstallation

Usage

viaXML

viaEditor

2

Page 3: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

3

Page 4: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Dozer

WhatisDozer?DozerisaJavaBeantoJavaBeanmapperthatrecursivelycopiesdatafromoneobjecttoanother.Typically,theseJavaBeanswillbeofdifferentcomplextypes.

Dozersupportssimplepropertymapping,complextypemapping,bi-directionalmapping,implicit-explicitmapping,aswellasrecursivemapping.Thisincludesmappingcollectionattributesthatalsoneedmmappingattheelementlevel.

PleasereadtheaboutpagefordetailedinformationonDozer.

Introduction

4

Page 5: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

WhyMap?Amappingframeworkisusefulinalayeredarchitecturewhereyouarecreatinglayersofabstractionbyencapsulatingchangestoparticulardataobjectsvs.propagatingtheseobjectstootherlayers(i.e.externalservicedataobjects,domainobjects,datatransferobjects,internalservicedataobjects).AmappingframeworkisidealforusingwithinMappertypeclassesthatareresponsibleformappingdatafromonedataobjecttoanother.

Fordistributedsystems,asideeffectisthepassingofdomainobjectsbetweendifferentsystems.Typically,youwon’twantinternaldomainobjectsexposedexternallyandwon’tallowforexternaldomainobjectstobleedintoyoursystem.

Mappingbetweendataobjectshasbeentraditionallyaddressedbyhandcodingvalueobjectassemblers(orconverters)thatcopydatabetweentheobjects.Mostprogrammerswilldevelopsomesortofcustommappingframeworkandspendcountlesshoursandthousandsoflinesofcodemappingtoandfromtheirdifferentdataobject.

Agenericmappingframeworksolvestheseproblems.Dozerisanopensourcemappingframeworkthatisrobust,generic,flexible,reusable,andconfigurable.

Dataobjectmappingisanimportantpartoflayeredserviceorientedarchitectures.Pickandchoosethelayersyouusemappingcarefully.Donotgooverboardasthereismaintenanceandperformancecostsassociatedwithmappingdataobjectsbetweenlayers.

ParallelObjectHierarchies

Therecouldbedifferentreasonsofwhyapplicationshouldsupportparallelobjecthierarhchies.Tonameafew:

IntegrationwithExternalCode

SerializationRequirements

FrameworkIntegration

SeparationofArchitecturalLayers

Insomecasesitisefficienttoguardyourcodebasefromfrequentlychangingobjecthierarchy,whichyoudonotcontroldirectly.InthiscaseDozerservesasabridgebetweenapplicationandexternalobjects.AsmappingisperformedinreflectivemannernotallchangesbreakyourAPI.ForexampleifobjectchangesfromNumbertoStringthecodewillkeepworkingasthisisresolvedautomatically.

SomeframeworksimposeSerializationconstraints,whichdoesnotallowsendinganyJavaobjectsthroughthewire.OneofthepopularexamplesisGoogleWebToolkit(GWT)framework,whichrestrictsdevelopertosendingonlyobjectscompiledtoJavaScriptandmarkedasSerializable.DozerhelpstoconvertRichDomainModeltoPresentationModel,whichsatisfiesGWTserializationrequirements.

DozerintegratesnicelywithframeworksuseJAXBimplementations.Withhelpofprovidedfactoryclasses,conversionbetweendomainmodelandXmlobjectsisdefinedinthesamewayasplainobjecttoobjectmappings.

Incomplexenterpriseapplicationitisoftenvaluabletoseparatedesigntoseveralarchitecturallayers.Eachofthemwouldresideonitsownabstractionlevel.Atypicalsimplifiedexamplewouldbepresentation,domainandpersistencelayers.EachofthislayerscouldhaveownsetofJavaBeansrepresentingdatarelevantforthislayer.Itisnotnecessarythatalldatawilltraveltotheupperlevelsofarchitecture.Forexamplethesamedomainobjectcouldhavedifferentmappingsdependantofthepresentationlayerrequirements.

WhyMap?

5

Page 6: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

WhyMap?

6

Page 7: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

GettingStarted

DownloadingtheDistribution

IfyouareusingApacheMaven,simplycopy-pastethisdependencytoyourproject.

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>6.4.0</version></dependency>

1stMapping

Foryourfirstmapping,letsassumethatthetwodataobjectsshareallcommonattributenames.

Mappermapper=DozerBeanMapperBuilder.buildDefault();DestinationObjectdestObject=mapper.map(sourceObject,DestinationObject.class);

AfterperformingtheDozermapping,theresultwillbeanewinstanceofthedestinationobjectthatcontainsvaluesforallfieldsthathavethesamefieldnameasthesourceobject.Ifanyofthemappedattributesareofdifferentdatatypes,theDozermappingenginewillautomaticallyperformdatatypeconversion.AtthispointyouhavecompletedyourfirstDozermapping.Latersectionswillgooverhowtospecifycustommappingsviacustomxmlfiles.

IMPORTANT:Forreal-worldapplicationsitisNOTrecommendedtocreateanewinstanceoftheMappereachtimeyoumapobjectsbutreusecreatedinstanceinstead.

SpecifyingCustomMappingsviaXML

Ifthetwodifferenttypesofdataobjectsthatyouaremappingcontainanyfieldsthatdon’tshareacommonpropertyname,youwillneedtoaddaclassmappingentrytoyourcustommappingxmlfile.ThesemappingsxmlfilesareusedatruntimebytheDozermappingengine.

Dozerautomaticallyperformsanytypeconversionwhencopyingthesourcefielddatatothedestinationfield.TheDozermappingengineisbi-directional,soifyouwantedtomapthedestinationobjecttothesourceobject,youdonotneedtoaddanotherclassmappingtothexmlfile.

IMPORTANT:Fieldsthatareofthesamenamedonotneedtobespecifiedinthemappingxmlfile.Dozerautomaticallymapsallfieldswiththesamepropertynamefromthesourceobjectintothedestinationobject.

i.e.:

<mapping><class-a>yourpackage.yourSourceClassName</class-a><class-b>yourpackage.yourDestinationClassName</class-b><field><a>yourSourceFieldName</a><b>yourDestinationFieldName</b></field></mapping>

ThecompleteDozermappingxmlfilewouldlooklikethefollowing.TheCustomMappingssectioncontainsmoreinformationonmappingoptionsthatareavailabletoyouformorecomplexusecases.

GettingStarted

7

Page 8: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<?xmlversion="1.0"encoding="UTF-8"?><mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttp://dozermapper.github.io/schema/bean-mapping.xsd"><configuration><stop-on-errors>true</stop-on-errors><date-format>MM/dd/yyyyHH:mm</date-format><wildcard>true</wildcard></configuration><mapping><class-a>yourpackage.yourSourceClassName</class-a><class-b>yourpackage.yourDestinationClassName</class-b><field><A>yourSourceFieldName</A><B>yourDestinationFieldName</B></field></mapping></mappings>

DozerandDependencyInjectionFrameworks

DozerisnotdependantofanyexistingDependencyInjectionframework(DI).Howeverthegeneralaimistosupportthemosttypicalusecaseswithready-to-usewrappers.CheckSpringIntegrationmanualforoptionofinitializingDozerincontextofSpringDIframework.

GettingStarted

8

Page 9: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Usage

DozerBeanMapper

Beforewegooversettingupcustomxmlbeanmappings,letuslookatasimpleexampleofusingDozer.TheDozermappingimplementationhasamethodcalledmapwhichtakesasourceobjectandeitheradestinationobjectordestinationobjectclasstype.Aftermappingthetwoobjectsitthenreturnsthedestinationobjectwithallofitsmappedfields.

Mappermapper=DozerBeanMapperBuilder.buildDefault();DestinationObjectdestObject=mapper.map(sourceObject,DestinationObject.class);

Or…

DestinationObjectdestObject=newDestinationObject();mapper.map(sourceObject,destObject);

Dozeroperatesintwogeneralmodes:implicitandexplicit.

Implicitmodeisactivatedbydefaultandtriestoresolvemappingsforyou.Itusessimpleassumptionsthatiftwoobjectsarepassedformappingthenbeanpropertieswiththesamenamesshouldbemapped.Ifthereareadditionalmappingsneeded,whichcannotbederivedbythenamingyoushouldaddthoseeitherviaXML,annotationsorAPI.

Explicitmodeassumesthatnomappingsshouldbeperformedor"guessed"untilyouhavespecifiedthosespecifically.Theamountofcodingishigherinexplicitmode,butsometimesyouwouldliketohavefullcontrolonwhatisgoingonduringthemappingsprocessandthisapproachisalsousedinmanyoftheproductiveapplications.Implicit/Explicitmappingswitchiscalled"wildcard"inDozer.

InjectingCustomMappingFiles

TheDozermappingxmlfile(s)defineanycustommappingsthatcan’tbeautomaticallyperformedbytheDozermappingengine.AnycustomDozermappingfilesneedtobeinjectedintotheMapperimplementationviaDozerBeanMapperBuilder#withMappingFiles(..)method.

Preferably,youwillbeusinganIOCframeworksuchasSpringfortheseDozerinjectionrequirements.Alternatively,theinjectionofmappingfilescanbedoneprogrammatically.Belowisaprogrammaticapproachtocreatingabeanmapper.NotethatthisisNOTtherecommendedwaytoretrievethebeanmapper.Eachnewinstanceneedstobeinitializedandthisconsumestimeaswellasresources.Ifyouareusingthemapperthiswayjustwrapitusingthesingletonpattern.

Mappermapper=DozerBeanMapperBuilder.create().withMappingFiles("dozerBeanMapping.xml","someOtherDozerBeanMappings.xml").build();

DestinationObjectdestObject=mapper.map(sourceObject,DestinationObject.class);

SpringIntegration

ThefollowingisanexamplehowtheMapperbeanwouldbeconfiguredviaSpring.

<beanid="mapper"class="com.github.dozermapper.core.DozerBeanMapper"><propertyname="mappingFiles"><list>

Usage

9

Page 10: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<value>dozer-global-configuration.xml</value><value>dozer-bean-mappings.xml</value><value>more-dozer-bean-mappings.xml</value></list></property></bean>

Usage

10

Page 11: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CustomMappingsViaDozerXMLFilesThissectionwillcoversettingupcustommappingsinxmlfile(s).Ifthetwodifferenttypesofdataobjectsthatyouaremappingcontainanyfieldsthatdon’tshareacommonpropertyname,youwillneedtoaddaclassmappingentrytoyourcustommappingxmlfile.ThesemappingsxmlfilesareusedatruntimebytheDozermappingengine.

Dozerautomaticallyperformsanytypeconversionwhencopyingthesourcefielddatatothedestinationfield.TheDozermappingengineisbi-directional,soifyouwantedtomapthedestinationobjecttothesourceobject,youdonotneedtoaddanotherclassmappingtothexmlfile.

Anexampleofamappingfile….

<?xmlversion="1.0"encoding="UTF-8"?><mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttp://dozermapper.github.io/schema/bean-mapping.xsd"><mapping><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><field><a>one</a><b>onePrime</b></field></mapping><mappingwildcard="false"><class-a>com.github.dozermapper.core.vo.TestObjectFoo</class-a><class-b>com.github.dozermapper.core.vo.TestObjectFooPrime</class-b><field><a>oneFoo</a><b>oneFooPrime</b></field></mapping></mappings>

Amappingselementhasmultiplemappingelements,eachwithclassmappingdeclarationsandfieldlevelmappings.Thewildcardattributeissettotruebydefault.Thismeansthatitwillautomaticallytrytomapeverypropertyinthetwoobjects.Whentheattributeissettofalseitwillonlymapexplicitlydefinedfields.

IMPORTANT:Propertiesthatareofthesamenamedonotneedtobespecifiedinthemappingxmlfile.Dozerautomaticallymapsallfieldswiththesamepropertynamefromthesourceobjectintothedestinationobject.

HowCustomMappingFilesAreLoaded

Dozerwillsearchtheentireclasspathlookingforthespecifiedfile.Thegenerallyacceptablewayofdistributingyourmappingsistobundletheminsideyourapplicationarchive.

Alternatively,youcanloadfilesfromoutsidetheclasspathbyprepending"file:"totheresourcename.Ex)"file:c:\somedozermapping.xml"

LoadingFilesfromInputStream

Sinceversion5.4.0itispossibletoloadXMLmappingfilesfromprovidedInputStreamobject.CheckDozerMapperclassforthecorrespondingAPIcalls.

MappingsviaXML

11

Page 12: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MappingsviaXML

12

Page 13: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

AnnotationMappings

WhyAnnotations?

OneofthedownsidesofusingDozerforthelongtimewasXml.SinceDozerstartedduringXml-hypeyearsmorethanfiveyearsagothatwasprettyobviouschoicebackthen.AfterthatJava5broughtusannotationsandnewindustryacceptedstyleofconfiguringbehaviourareDomain-SpecificLanguages.DSL-likesupportisprovidedinformofmappingAPI,butsinceversion5.3.2Dozerstartsprovidingannotationssupportaswell.

Theobviousreasonstouseannotationsistoavoidduplicatingfieldandmethodnamesinyourmappingcode.Theannotationcanbeputontothemappedpropertyitselfthusreducingtheamountofcode.Howevertherearecaseswhenannotationsshouldbeavoidedorevenimpossibletouse.Someofthemarethefollowing:

Youaremappingclasses,whicharenotunderyourcontrol,butprovidedinlibraries;

Themappingsarequitecomplexandrequiremanyconfigurations;

InthefirstcaseyoucouldbemappingJAXBgeneratedentitiesorthird-partyDTOsandhavenopossibilitytoputannotations.Inthesecondcasethereisachoiceofputtinglotsofmulti-lineannotationsorisolatingthemappingcodewithcertainduplicationofentitynames.Overannotatedbeanscouldbeproblematictoreadandunderstand.

Usage

WARNING:AnnotationsupportinDozerisexperimentalanddoesnotcovercomplexusecasesyet.HoweveritmaybeusefultoimplementthatsimplestmappingsyouhavehadtodoinXmlorAPIbefore.

Theideaisverysimple.Youput@Mappingannotationeitherongetteroffielddirectly.IfDozerfindsthatitaddsabi-directionalmapping.Itmeansthatputtingannotationoncewillcreatemappingsforbothconversiontypes.Typeconversions(e.g.String-Long)willbechosenautomatically.Globalcustomconvertersareresolvedaswell.Annotationsworkonlyifaconversionissubjecttowildcardrule(activebydefault).Thefollowingexampledemonstratesannotationsinaction.

publicclassSourceBean{

privateLongid;

privateStringname;

@Mapping("binaryData")privateStringdata;

@Mapping("pk")publicLonggetId(){returnthis.id;}

publicStringgetName(){returnthis.name;}}

publicclassTargetBean{

privateStringpk;

privateStringname;

viaAnnotations

13

Page 14: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

privateStringbinaryData;

publicvoidsetPk(Stringpk){this.pk=pk;}

publicvoidsetName(Stringname){this.name=name;}}

MappingthegivenbeanswithDozerwillresultinallthreefieldsbeingmapped.Property"name"willbemappedbynamingconvention.Property"id"willbetransformedto"pk".Field"data"willbemovedto"binaryData".Donotworryaboutprivatemodifier;itwillbehandledautomatically.

CurrentlyDozeroffersonlyoneannotation,butthenextoneswillbeaddedinfollowingreleases.Asfornowyoucanmixandmatchallflavoursofmappingtypestoachievethedesiredeffect:Xml,APIandAnnotations.

viaAnnotations

14

Page 15: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

APIMappings

XMLMappingFlaws

XML-basedapproachisstableandisusedinmanyproductionprojects.However,itimposesseverallimitations.

First,andmostimportant,isthatitcannotbedynamicallygenerated.AllXMLmappingsshouldbepresentonDozerstart-upandcannotbemodifiedafterwards.Therearetrickyways,whenyoucangenerateandputmappingstothefilesystembyyourowntemplatingengine,butthisapproachisnotsupportedbyDozeritself.Bygeneratingcustommappingsyouareabletoautomaterepetitivechunksoflow-levelDozerlanguage.

SecondproblemisthatyouareforcedtoduplicateallofyourBeanclassnamesinXmlmappings.Thisleadstolotsoftypingandcopy-pasteprogramming.ThiscanbepartlycompensatedbyuseofExpressionLanguageinsideXml,butitisnotsolvingalloftheproblems.

RefactoringsupportislimitedasIDEshouldkeeptrackofclassnamesinXmlfilesandchangethemwhenyourenameormovethereferencedclass.Auto-completionsupportisalsonotavailableinallIDEs.

APIMappings

APImappingsareintendedtosolveallofthementionedproblems.TopreservebackwardscompatibilityAPImappingscanbecombinedwithexistingXmlmappings.Infactsomepartsoftheconfiguration(e.g.globalconfigurationblock)areonlypossibletoexpressinXmlformat.

Togetafeelingofwhatarethesemappingstakealookatthefollowingcodeexample.

importcom.github.dozermapper.core.classmap.RelationshipType;importcom.github.dozermapper.core.loader.api.BeanMappingBuilder;importcom.github.dozermapper.core.loader.api.FieldsMappingOptions;importcom.github.dozermapper.core.loader.api.TypeMappingOptions;

importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.collectionStrategy;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.copyByReference;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.customConverter;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.customConverterId;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.hintA;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.hintB;importstaticcom.github.dozermapper.core.loader.api.FieldsMappingOptions.useMapId;importstaticcom.github.dozermapper.core.loader.api.TypeMappingOptions.mapId;importstaticcom.github.dozermapper.core.loader.api.TypeMappingOptions.mapNull;

publicclassMyClass{

publicvoidcreate(){BeanMappingBuilderbuilder=newBeanMappingBuilder(){protectedvoidconfigure(){mapping(Bean.class,Bean.class,TypeMappingOptions.oneWay(),mapId("A"),mapNull(true)).exclude("excluded").fields("src","dest",copyByReference(),collectionStrategy(true,RelationshipType.NON_CUMULATIVE),hintA(String.class),hintB(Integer.class),FieldsMappingOptions.oneWay(),useMapId("A"),customConverterId("id")

viaAPI

15

Page 16: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

).fields("src","dest",customConverter("com.github.dozermapper.core.CustomConverter"));}};}}

ConstructedbuilderobjectshouldbethenpassedtoDozerBeanMapperBuilder.ItispossibletoaddmultipleBuilderclasses.

Mappermapper=DozerBeanMapperBuilder.create().withMappingBuilder(builder).build();

viaAPI

16

Page 17: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ConfigurationDozerconfigurationpropertiescanbecustomizedviaanoptionalDozerpropertiesfile.Bydefault,Dozerwilllookforafilenameddozer.propertiestoloadconfigurationproperties.Ifapropertiesfileisnotfoundorspecified,defaultvalueswillbeused.

Dozerisdistributedwithanexampledozer.propertiesfilein/configthatshowsthevariousoptions.Justputtheexamplefileinyourclasspathandcustomizeit.

AnalternativeDozerpropertiesfilecanbespecifiedviathedozer.configurationsystemproperty.ex)-Ddozer.configuration=someDozerConfigurationFile.properties

Table1.DozerConfigurationProperties

PropertyName Description ValidValues Default

dozer.el.enabled

SpecifieswhetherduringXmlmappingsparsingDozerwillrecognizeELexpressions.

true false false

dozer.cache.converter-by-dest-type-maxsize

SpecifiesthemaxsizeforoneofDozersinternalcaches.

0-Long.MAX_VALUE 10000

dozer.cache.super-type-maxsize

SpecifiesthemaxsizeforoneofDozersinternalcaches

0-Long.MAX_VALUE 10000

dozer.beans.proxy-resolver-bean

SpecifiesimplementationofDozerProxyResolvertobeused

Validclassname Defaultimplementation

dozer.beans.class-loader-bean

SpecifiesimplementationofDozerClassLoadertobeused

Validclassname Defaultimplementation

Configuration

17

Page 18: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ConfigurationviaXMLThemajorityofDozer’sbehaviourcanbeconfiguredfromwithinXMLmappingfiles.Settingscanappearinsidefivedifferentscopeswhichaffecttheelementstheyareappliedto:Global,perclassmapping,atindividualclasslevel,perfieldmapping,andatindividualfieldlevel.

ConfigurationScopes

GlobalScope

Theconfigurationblockisusedtosettheglobaldefaultsettings.Also,anyCustomConvertersaredefinedinthissection.Theconfigurationblockisentirely"optional".

Dozersupportstheabilitytohavemultiplemappingfiles.Eachofthesemappingfilescanhavetheirownconfigurationblock.Amappingwillinherititsconfigurationfromthemappingfilethatitisstoredin.Implicitmappingswillinheritthedefaultvaluesforconfiguration.

Thefollowingisthesampleconfigurationblockfromtheexamplemappingsfile:

<configuration><date-format>MM/dd/yyyyHH:mm</date-format><stop-on-errors>true</stop-on-errors><wildcard>true</wildcard><custom-converters><!--thesearealwaysbi-directional--><convertertype="com.github.dozermapper.core.converters.TestCustomConverter"><class-a>com.github.dozermapper.core.vo.TestCustomConverterObject</class-a><class-b>another.type.to.Associate</class-b></converter></custom-converters></configuration>

AllglobalsettingsappearasseparateXMLtagscontainingtheirvalue.

PerClassMapping

Globalsettings(ortheirdefaults)canbeoverriddenattheindividualmappinglevel.Here,configurationvaluesaresetusingname="value"attributes.Theywillaffectallmappingoperationsbetweenthetwoclasses.

<mappingwildcard="false"date-format="MM/dd/yyyyHH:mm"><class-a>com.github.dozermapper.core.vo.SpringBean</class-a><class-b>com.github.dozermapper.core.vo.SpringBeanPrime</class-b><field><a>anAttributeToMap</a><b>anAttributeToMapPrime</b></field></mapping>

AtIndividualClassLevel

Sometimes,youmaywanttoapplyasettingonlytooneofthetwoclasses.Thiscanbeachievedbyplacingtheattributeinsidetheclass-aorclass-btag:

<mapping><class-ais-accessible="true">com.github.dozermapper.core.vo.SpringBean</class-a>

ConfigurationviaXML

18

Page 19: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<class-b>com.github.dozermapper.core.vo.SpringBeanPrime</class-b><field><a>anAttributeToMap</a><b>anAttributeToMapPrime</b></field></mapping>

PerFieldMapping

Likewise,youcanchangethemappingbehaviourforspecificfieldpairs:

<mapping><class-a>com.github.dozermapper.core.vo.SpringBean</class-a><class-b>com.github.dozermapper.core.vo.SpringBeanPrime</class-b><fieldremove-orphans="false"><a>anAttributeToMap</a><b>anAttributeToMapPrime</b></field></mapping>

AtIndividualFieldLevel

Finally,somesettingscanbeappliedtoasinglefield:

<mapping><class-a>com.github.dozermapper.core.vo.SpringBean</class-a><class-b>com.github.dozermapper.core.vo.SpringBeanPrime</class-b><field><aget-method="getTheAttribute">anAttributeToMap</a><b>anAttributeToMapPrime</b></field></mapping>

AvailableConfigurationSettings

Thefollowingtableliststheavailableconfigurationoptionsandmappingdirectives,inwhichscopestheycanappear,andthesectionofthemanualcontainingmoreinformation:

Name Global ClassMapping

SingleClass

FieldMapping

SingleField

ManualSection

allowed-exceptions X seebelow

custom-converter X Custom

Converters

custom-converter-id X Custom

Converters

custom-converter-param

X CustomConverters

copy-by-reference X CopyBy

Reference

copy-by-references X CopyBy

Reference

ConfigurationviaXML

19

Page 20: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

create-method X X

CustomCreateMethod

bean-factory X X X

CustomBeanFactories

date-format X X XStringtoDateMapping

factory-bean-id X

CustomBeanFactories

get-method X CustomMethods

is-accessible X X

Mappingimmutabletypes

key X MapMapping

map-empty-string X X X Excluding

Fields

map-id XContextBasedMapping

map-null X X X ExcludingFields

map-set-method X X Map

Mapping

map-get-method X X Map

Mapping

relationship-type X X X Collection

Mapping

remove-orphans X Collection

Mapping

set-method X CustomMethods

skip-constructor X

Mappingimmutabletypes

stop-on-errors X seebelow

ConfigurationviaXML

20

Page 21: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

trim-strings X X seebelow

type X X One-WayMapping

variables X ExpressionLanguage

wildcard X X seebelow

wildcard-case-insensitive

X X seebelow

Errorhandling(stop-on-errors,allowed-exceptions)

Bydefault,ifDozerencountersanerrorwhileperformingafieldmapping,anexceptionisthrownandthemappingaborted.Whilethisistherecommendedbehaviour,Dozercanbeinstructedtoignoretheerrorandsimplycontinuewiththenextfield,viathestop-on-errorspolicy.

YoucanalsospecifyexceptionsthatshouldcauseDozertostopandrethrowthem,evenifstop-on-errorsissettofalse,usingtheallowed-exceptionselement:

<configuration><stop-on-errors>false</stop-on-errors><allowed-exceptions><exception>org.example.UnrecoverableError</exception><exception>org.example.BadException</exception></allowed-exceptions></configuration>

TrimmingStrings(trim-strings)

Asthenamesuggests,trim-stringsappliesJava’sString.trim()tothesourcevaluebeforecallingthetargetbeans’ssetter.

Wildcardmapping(wildcard,wildcard-case-insensitive)

Perdefault,Dozermapsallfieldsbetweensourceandtargetbeanthatsharethesamename("wildcardmapping").Listingfieldsinmappingdefinitionsdoesnotoverridethisbehaviour,exceptforthegivenfields.Forexample,giventhefollowingclasses

classPerson{privateStringfirstName;privateStringlastName;}

classContact{privateStringfirstName;privateStringsurname;}

andthemappingdefinition

<mapping>

ConfigurationviaXML

21

Page 22: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<class-a>com.github.dozermapper.core.vo.Person</class-a><class-b>com.github.dozermapper.core.vo.Contact</class-b><field><a>lastName</a><b>surname</b></field></mapping>

amappingfromaPersonobjectontoaContactwillmaplastNametosurnameandfirstNametofirstName,eventhoughthelatterpairisnotmentionedinthemappingdefinition.

Youcandisablewildcardmappinggloballyorattheclassmappinglevelbysettingwildcardtofalse.Ifyoudo,youhavetoexplicitlyspecifyeachpairoffieldsthatshouldbemapped:

<mappingwildcard="false"><class-a>com.github.dozermapper.core.vo.Person</class-a><class-b>com.github.dozermapper.core.vo.Contact</class-b><field><a>lastName</a><b>surname</b></field><field><a>firstName</a><b>firstName</b></field></mapping>

UptoDozerversion5.4.0,wildcardmappingswerecaseinsensitive.CurrentversionsofDozeronlyautomaticallymapfieldswiththeexactsamename.Youcanenabletheoldcaseinsensitivebehaviourbysettingthewildcard-case-insensitivepolicytotrue.Then,forexampleasourcefieldnamedcamelCasewillbemappedtotargetfieldcamelcase(andviceversa).

ConfigurationviaXML

22

Page 23: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ConfigurationviaAPIIfyouareusingtheMapperBuildertodefineyourmappings,youcandeclaremapping,class,andfieldconfigurationsettingsprogrammatically:

Mappermapper=DozerBeanMapperBuilder.create().withMappingBuilder(newBeanMappingBuilder(){@Overrideprotectedvoidconfigure(){mapping(type(A.class).mapEmptyString(true),type(B.class),TypeMappingOptions.wildcardCaseInsensitive(true)).fields(field("fieldOfA").getMethod("getTheField"),field("fieldOfB"),FieldsMappingOptions.oneWay());}}).build();

GlobalconfigurationiscurrentlynotsupportedbytheAPI.

PleaseseeConfigurationviaXMLforalistoftheavailableconfigurationsettings.

ConfigurationviaAPI

23

Page 24: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MappingClassesAnexampleofmappingtwoclassesisdefinedbelow.Note:Explicitxmlmappingfor2classesisnotrequiredifallthefieldmappingbetweensrcanddestobjectcanbeperformedbymatchingonattributename.Customxmlclassmappingisonlyrequiredwhenyouneedtospecifyanycustomfieldmappings.

<mappings><mapping><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><!--Anycustomfieldmappingxmlwouldgohere--></mapping></mappings>

Thesemappingsarebi-directionalsoyouwouldneverneedtodefineanXMLmapforTestObjectPrimetoTestObject.Ifthesetwoclasseshadreferencestocomplextypesthatneededtypetransformation,youwouldalsodefinethemasmappings.Dozerrecursivelygoesthroughanobjectandmapseverythinginit.Datatypeconversionisperformedautomatically.Dozeralsosupportsnoattributemappingsatall.Ifsuppliedtwoclassesthatarenotmapped,itsimplytriestomappropertiesthatarethesamename.

MappingClasses

24

Page 25: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

BasicPropertyMapping

ImplicitPropertyMapping(bi-directional)

MatchingfieldnamesareautomaticallyhandledbyDozer.

Propertiesthatareofthesamenamedonotneedtobespecifiedinthemappingxmlfile.

SimpleMappings(bi-directional)

Wewillstartoffsimple.Ifyouhavetwopropertieswithdifferentnamestheycanbemappedassuch:

<field><a>one</a><b>onePrime</b></field>

Datatypeconversion

DatatypecoversionisperformedautomaticallybytheDozermappingengine.Currently,Dozersupportsthefollowingtypesofconversions:(theseareallbi-directional)

PrimitivetoPrimitiveWrapper

PrimitivetoCustomWrapper

PrimitiveWrappertoPrimitiveWrapper

PrimitivetoPrimitive

ComplexTypetoComplexType

StringtoPrimitive

StringtoPrimitiveWrapper

StringtoComplexTypeiftheComplexTypecontainsaStringconstructor

StringtoMap

CollectiontoCollection

CollectiontoArray

MaptoComplexType

MaptoCustomMapType

EnumtoEnum

Eachofthesecanbemappedtooneanother:java.util.Date,java.sql.Date,java.sql.Time,java.sql.Timestamp,java.util.Calendar,java.util.GregorianCalendar

StringtoanyofthesupportedDate/CalendarObjects.

ObjectscontainingatoString()methodthatproducesalongrepresentingtimein(ms)toanysupportedDate/Calendarobject.

RecursiveMapping(bi-directional)

BasicPropertyMapping

25

Page 26: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

DozersupportsfullClasslevelmappingrecursion.Ifyouhaveanycomplextypesdefinedasfieldlevelmappingsinyourobject,DozerwillsearchthemappingsfileforaClasslevelmappingbetweenthetwoClassesthatyouhavemapped.Ifyoudonothaveanymappings,itwillonlymapfieldsthatareofthesamenamebetweenthecomplextypes.

BasicPropertyMapping

26

Page 27: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

InheritanceMapping

ReducingMappingXMLwhenusingbaseclassattributes

Propertiesthatareofthesamenamedonotneedtobespecifiedinthemappingxmlfileunlesshintsareneeded.

IfyouaremappingsubclassesthatalsohavehavebaseclassattributesrequiringmappingXML,youmightbeinclinedtoreproducebaseclassfieldmapsineachsubclassmappingelement,likethefollowingexample:

<mapping><class-a>com.github.dozermapper.core.vo.SubClass</class-a><class-b>com.github.dozermapper.core.vo.SubClassPrime</class-b><field><!--thisisthesameforallsubclasses--><a>superAttribute</a><b>superAttr</b></field><field><a>attribute2</a><b>attributePrime2</b></field></mapping><mapping><class-a>com.github.dozermapper.core.vo.SubClass2</class-a><class-b>com.github.dozermapper.core.vo.SubClassPrime2</class-b><field><!--thisisthesameforallsubclasses--><a>superAttribute</a><b>superAttr</b></field><field><a>attribute2</a><b>attributePrime2</b></field></mapping>

Inthepreviousmapping,someofthefieldswerefromacommonbaseclass,butyouhadtoreproducethemintoeachmappingofthesubclasses.

However,abetterwaytodoitwouldbetomapthebaseclassindividually.Thiscanbedoneforeachbaseclass(inthecaseofalargerheirarchy).Assumingthebaseclassname,belowistherefactoredmappingxml:

<mapping><class-a>com.github.dozermapper.core.vo.SuperClass</class-a><class-b>com.github.dozermapper.core.vo.SuperClassPrime</class-b><field><a>superAttribute</a><b>superAttr</b></field></mapping><mapping><class-a>com.github.dozermapper.core.vo.SubClass</class-a><class-b>com.github.dozermapper.core.vo.SubClassPrime</class-b><field><a>attribute</a><b>attributePrime</b></field></mapping><mapping><class-a>com.github.dozermapper.core.vo.SubClass2</class-a>

InheritanceMapping

27

Page 28: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<class-b>com.github.dozermapper.core.vo.SubClassPrime2</class-b><field><a>attribute2</a><b>attributePrime2</b></field></mapping>

Thefollowingimagesexplainsomeofthedifferentscenariosdozerhandles.Eachdiagramshowstwomappedclasshierarchiesandexistingrelations,whichDozerrecognizesandmaps.

Scenario1showsthatifyoumapSubClasstoClassPrimeallattributesfromSuperClass→ClassPrimewillbemappedaswell.

Scenario2showsthatDozerhasnolimitationsontheinheritancedepthitanalyzestofindparentmappings.

InheritanceMapping

28

Page 29: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Scenario3showsthatitispossibletomaptwocollectionswithdifferentsubctypesofthesameparenttype.Thisisdonebyprovidinghintstothecollectionmapping,describingallpotentialsubclasses.

<field><a>aList</a><b>bList</b><a-hint>B1,B2</a-hint><b-hint>BPrime1,BPrime2</b-hint></field>

InheritanceMapping

29

Page 30: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ContextBasedMappingContextbasedmappingcanbespecifiedbyusingthemap-idattribute.Notethatwealsosupportnestedcontextmappingbyspecifyingamap-idatthefieldlevel.

<mappingmap-id="caseA"><class-a>com.github.dozermapper.core.vo.context.ContextMapping</class-a><class-b>com.github.dozermapper.core.vo.context.ContextMappingPrime</class-b><field-exclude><a>loanNo</a><b>loanNo</b></field-exclude><fieldmap-id="caseC"><a>contextList</a><b>contextList</b><b-hint>com.github.dozermapper.core.vo.context.ContextMappingNestedPrime</b-hint></field></mapping><mappingmap-id="caseB"><class-a>com.github.dozermapper.core.vo.context.ContextMapping</class-a><class-b>com.github.dozermapper.core.vo.context.ContextMappingPrime</class-b></mapping><mappingmap-id="caseC"><class-a>com.github.dozermapper.core.vo.context.ContextMappingNested</class-a><class-b>com.github.dozermapper.core.vo.context.ContextMappingNestedPrime</class-b><field-exclude><a>loanNo</a><b>loanNo</b></field-exclude></mapping><mappingmap-id="caseD"><class-a>com.github.dozermapper.core.vo.context.ContextMappingNested</class-a><class-b>com.github.dozermapper.core.vo.context.ContextMappingNestedPrime</class-b></mapping>

TouseaparticularcontextwheninvokingtheMapper,yousimplyspecifythemap-idinyourmappingcall.

ContextMappingPrimecmpA=mapper.map(cm,ContextMappingPrime.class,"caseA");

ContextBasedMapping

30

Page 31: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

One-WayMappingYoucansethowamappingdefinitionbehavesasfarasdirectiongoes.Ifyouonlywanttomaptwoclassestogoone-wayyoucansetthisatthemappinglevel.Thedefaultisbi-directional.ThiscanbesetatthemappinglevelORthefieldlevel.Whenone-wayisspecified,"a"isalwaysthesrcobjectand"b"isalwaysthedestinationobject.

<mappingtype="one-way"><class-a>com.github.dozermapper.core.vo.TestObjectFoo</class-a><class-b>com.github.dozermapper.core.vo.TestObjectFooPrime</class-b><field><a>oneFoo</a><b>oneFooPrime</b></field></mapping>

Inthefollowingexampletheone-wayfieldsareonlymappedwhen"a"objectismappedto"b"object.If"b"ismappedto"a",thenthefieldisnotmapped.

<mapping><class-a>com.github.dozermapper.core.vo.TestObjectFoo2</class-a><class-b>com.github.dozermapper.core.vo.TestObjectFooPrime2</class-b><fieldtype="one-way"><a>oneFoo2</a><b>oneFooPrime2</b></field><fieldtype="one-way"><a>oneFoo3.prime</a><b>oneFooPrime3</b></field></mapping>

ExcludingFieldsOne-Way

Dozersupportsfieldexcludesgoingone-wayasshownintheexample.Intheexamplethefieldisonlyexcludedwhen"a"ismappedto"b".If"b"ismappedto"a",thenthefieldisnotexcluded.

<field-excludetype="one-way"><a>fieldToExclude</a><b>fieldToExclude</b></field-exclude>

One-WayMapping

31

Page 32: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CopyingByObjectReferenceDozersupportscopyinganobjectbyreference.Noconversion/transformationisdoneforsuchobjects.Thisapproachallowstodecreaseanumberofobjectallocations,butisapplicableonlywhenJavaBeansaretobethrownaway(GarbageCollected)aftertransformation.Thisapproachisgenerallyrecommendedforperformancetuningofthemappingprocesswhenpossible.Makesurethatbothobjecttypesarethesameoryouwillrunintocastingproblems.Thedefaultvalueis'false'.

<fieldcopy-by-reference="true"><a>copyByReference</a><b>copyByReferencePrime</b></field>

Thisisalsosupportedattheclasslevel.Justdefinetheclassesyouwanttobecopiedbyreferenceintheconfigurationblock.

<configuration><copy-by-references><copy-by-reference>com.github.dozermapper.core.vo.NoExtendBaseObjectGlobalCopyByReference</copy-by-reference></copy-by-references></configuration>

Ontheclasslevelwildcardexpressionsareallowed.Copybyreferenceisappliedviamask,whichcaninlcudemultiplewildcard(*)characters.

<configuration><copy-by-references><copy-by-reference>com.github.dozermapper.core.vo.*</copy-by-reference><copy-by-reference>com.github.dozermapper.core.*.vo.*DTO</copy-by-reference></copy-by-references></configuration>

Referencingself(this)inafieldmapping

UsingafieldmappingitispossibletomapwhereN==0(self,orthis).InthefollowingexampleSimpleAccountismappedtoAddress.ItisalsomappedtoAccount.SupposeAddresswasanattributeonAccount.HowcouldwemapthevaluesonSimpleAccounttothatproperty?Theansweristousethekeyword(this)todenoteusingtheclassbeingmappedasthesourceobject.

<mapping><classa>com.github.dozermapper.core.vo.self.SimpleAccount</classa><classb>com.github.dozermapper.core.vo.self.Account</classb><field><a>this</a><b>address</b></field></mapping><mapping><classa>com.github.dozermapper.core.vo.self.SimpleAccount</classa><classb>com.github.dozermapper.core.vo.self.Address</classb>

CopyingByObjectReference

32

Page 33: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<field><a>streetName</a><b>street</b></field></mapping>

CopyingByObjectReference

33

Page 34: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

DeepPropertyMappingItispossibletomapdeepproperties.AnexamplewouldbewhenyouhaveanobjectwithaStringproperty.YourotherobjecthasaStringpropertybutitisseverallevelsdeepwithintheobjectgraph.IntheexamplebelowtheDestDeepObjhasnestedattributeswithintheobjectgraphthatneedtobemapped.Typehintsaresupportedfordeepfieldmappings.Theattributescopy-by-reference,type=one-way,andrelationship-typecanalsobeused.

<mapping><class-a>com.github.dozermapper.core.vo.deep.SrcDeepObj</class-a><class-b>com.github.dozermapper.core.vo.deep.DestDeepObj</class-b><field><a>srcNestedObj.src1</a><b>dest1</b></field><field><a>srcNestedObj.src2</a><b>dest2</b></field><field><a>srcNestedObj.srcNestedObj2.src5</a><b>dest5</b></field><field><!--java.util.Listtojava.util.List--><a>srcNestedObj.hintList</a><b>hintList</b><a-hint>java.lang.String</a-hint><b-hint>java.lang.Integer</b-hint></field><field><a>srcNestedObj.hintList2</a><b>hintList2</b><a-hint>com.github.dozermapper.core.vo.TheFirstSubClass</a-hint><b-hint>com.github.dozermapper.core.vo.TheFirstSubClassPrime</b-hint></field><fieldcopy-by-reference="true"><a>srcNestedObj.hintList3</a><b>hintList3</b></field></mapping>

DeepIndexedMapping

Indexedmappingwithindeepmappingissupported.

<field><a>offSpringName</a><b>pets[1].offSpring[2].petName</b></field>

DestinationHintsareNOTrequirediftheindexedcollectionisanArrayorifyouareusingjdk1.5Generics.Dozerisabletoautomaticallydeterminethepropertytypefortheseusecases.ButyouwillneedtoprovidehintsifthedatatypesarenotArraysorifyouarenotusingGenerics.ThisisrequiredsothatDozerknowswhattypesofdestobjectstocreatewhileittraversesthedeepfieldmapping.

Thefollowingisanexampleofusinghints…..

<field><a>someField</a>

DeepPropertyMapping

34

Page 35: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<b>someList[1].someOtherList[0].someOtherField</b><b-deep-index-hint>com.github.dozermapper.core.vo.TestObject,com.github.dozermapper.core.vo.AnotherTestObject</b-deep-index-hint></field>

DeepPropertyMapping

35

Page 36: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

IndexedPropertyMappingFieldsthatneedtobelookeduporwrittentobyindexedpropertyaresupported.

<mapping><class-a>com.github.dozermapper.core.vo.Individuals</class-a><class-b>com.github.dozermapper.core.vo.FlatIndividual</class-b><field><a>usernames[0]</a><b>username1</b></field><field><a>usernames[1]</a><b>username2</b></field><field><a>individual.username</a><b>username2</b></field><field><a>secondNames[1]</a><b>secondName1</b></field><field><a>secondNames[2]</a><b>secondName2</b></field><field><a>aliases.otherAliases[0]</a><b>primaryAlias</b></field></mapping>

IndexedPropertyMapping

36

Page 37: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ExcludingFieldsDozersupportsexcludingfieldsfromamappingusingthefield-excludetag.Wealsosupportfieldexcludesgoingone-wayasshownintheexample.

<field-exclude><a>fieldToExclude</a><b>fieldToExclude</b></field-exclude>

<field-excludetype="one-way"><a>fieldToExclude</a><b>fieldToExclude</b></field-exclude>

Wildcard-excludingdefaultfieldmappings

There’salsoaflag(wildcard)setonclassmappingwhichcontrolswhetherthedefaultmapping(whichappliestopairofpropertiesofthesamename)shouldbedone.Thedefaultvalueistrue.Forexample:

<mappingwildcard="false"><class-a>com.github.dozermapper.core.vo.AnotherTestObject</class-a><class-b>com.github.dozermapper.core.vo.AnotherTestObjectPrime</class-b><field><a>field1</a><b>field1</b></field></mapping>

Thisconfigurationwouldcauseonlythefieldsfield1inbothclassestobemapped,evenifbothclassesshareapropertywiththesamenamecalled`field2`.

ExcludeMappingNullValues

Youcanbypassthemappingofnullvalues.Ifthisisspecified,thedestfieldmappingisbypassedatruntimeandthedestinationvaluesettermethodwillnotbecalledifthesrcvalueisnull.Thiscanbespecifiedatthemappingorclasslevel.Forexample:

<mappingmap-null="false"><class-a>com.github.dozermapper.core.vo.AnotherTestObject</class-a><class-b>com.github.dozermapper.core.vo.AnotherTestObjectPrime</class-b><field><a>field4</a><b>to.one</b></field></mapping>

OR…

<mapping><class-a>com.github.dozermapper.core.vo.AnotherTestObject</class-a><class-bmap-null="false">com.github.dozermapper.core.vo.AnotherTestObjectPrime</class-b><field><a>field4</a><b>to.one</b></field>

ExcludingFields

37

Page 38: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

</mapping>

ExcludeMappingEmptyStrings

YoucanbypassthemappingofemptyStringvalues.Ifthisisspecified,thedestfieldmappingisbypassedatruntimeandthedestinationvaluesettermethodwillnotbecalledifthesrcvalueisanemptyString.Thiscanbespecifiedatthemappingorclasslevel.Forexample:

<mappingmap-empty-string="false"><class-a>com.github.dozermapper.core.vo.AnotherTestObject</class-a><class-b>com.github.dozermapper.core.vo.AnotherTestObjectPrime</class-b><field><a>field4</a><b>to.one</b></field></mapping>

OR…

<mapping><class-a>com.github.dozermapper.core.vo.AnotherTestObject</class-a><class-bmap-empty-string="false">com.github.dozermapper.core.vo.AnotherTestObjectPrime</class-b><field><a>field4</a><b>to.one</b></field></mapping>

ExcludingFields

38

Page 39: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MappingConcepts

AssemblerPattern

DozercanbeusedasanAssembler.MartinFowlerhasagreatexplanationofwhyandwhenyouwoulduseanAssembler.Basically,itisawaytotakemultiplefinegrainobjectsandcreateonecoarsegrainobjectusedfordatatransfer.Aslongasyouhavemappingsdefinedforeachofyourfinegrainedobjectstoyourcoarsegrainobjectyoucancallthemappermultipletimestoachievethedesiredassemblerpattern.

mapper.map(sourceA,ClassB.class);

Let’ssaythatClassA,ClassB,andClassCallmaptoClassD.Firstcreatetheseindividualmappingsinthemappingfile.Next,callthemapperonceforeachmapping.Notethatthiswouldalsoworkinabi-directinonalmanner.

ClassDd=newClassD();mapper.map(sourceA,d);mapper.map(sourceB,d);mapper.map(sourceC,d);

AssemblerPattern

39

Page 40: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MappingimmutabletypesYoucancreateobjectswhenconstructorisnotavailable,orwhenthereisnono-argsconstructorintheclass.Featureisdesignedformappingimmutabletypes.Touseit,atthemappingleveladdanoptiontoskiptheconstructor,thenatthefieldlevelchoosetoinjectthevaluedirectlytothefield,skippingthesetter.

<mapping><class-a>com.github.dozermapper.core.vo.AnyExternalModelClass</class-a><class-bskip-constructor="true">com.github.dozermapper.core.vo.ImmutableModelClass</class-b><field><a>externalModelField</a><bis-accessible="true">ourFinalField</b></field></mapping>

Mappingimmutabletypes

40

Page 41: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

EnumMappingTomapanenumsvaluetoanotherenumisshownbelow.

<field><a>status</a><b>statusPrime</b></field>

Basedonthefollowingcode:

enumStatus{PROCESSING,SUCCESS,ERROR}

publicclassUserGroup{

privateStatusstatus;

publicStatusgetStatus(){returnstatus;}

publicvoidsetStatus(Statusstatus){this.status=status;}

}

enumStatusPrime{PROCESSING,SUCCESS,ERROR}

publicclassUserGroupPrime{

privateStatusPrimestatusPrime;

publicStatusPrimegetStatusPrime(){returnstatusPrime;}

publicvoidsetStatusPrime(StatusPrimestatusPrime){this.statusPrime=statusPrime;}

}

Enums

41

Page 42: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

StringtoDateMappingAdateformatfortheStringcanbespecifiedatthefieldlevelsothatthenecessarydatatypeconversioncanbeperformed.

<field><adate-format="MM/dd/yyyyHH:mm:ss:SS">dateString</a><b>dateObject</b></field>

Adefaultdateformatcanalsobespecifiedattheclassmappinglevel.Thisdefaultdateformatwillbeappliedtoallfieldmappingsunlessitisoverriddenatthefieldlevel.

<mappingdate-format="MM-dd-yyyyHH:mm:ss"><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><field><a>dateString</a><b>dateObject</b></field></mapping>

Adefaultdateformatcanalsobespecifiedattheverytopmappingslevel.Thisdefaultdateformatwillbeappliedtoallfieldmapppingsunlessitisoverriddenatalowerlevel

<mappings><configuration><date-format>MM/dd/yyyyHH:mm</date-format></configuration><mappingwildcard="true"><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><field><a>dateString</a><b>dateObject</b></field></mapping><mapping><class-a>com.github.dozermapper.core.vo.SomeObject</class-a><class-b>com.github.dozermapper.core.vo.SomeOtherObject</class-b><field><a>srcField</a><b>destField</b></field></mapping></mappings>

StringtoDate

42

Page 43: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CollectionandArrayMappingDozerautomaticallymapsbetweencollectiontypesandautomaticallyperformsanytypeconversion.Eachelementinthesourcecollectionismappedtoanelementinthedestobject.Hintsareusedtospecifywhattypeofobjectsarecreatedinthedestinationcollection.ThefollowingcollectionmappingisautomaticallyhandledbyDozer:(Theseareallbi-directional)

ListtoList

ListtoArray

ArraytoArray

SettoSet

SettoArray

SettoList

UsingHintsforCollectionMapping

HintsarenotrequiredifyouareusingJDK1.5GenericsorArraysbecausethetypescanbeautodetectedbyDozer.ButifyouarenotusinggenericsorArrays,toconvertaCollection/ArraytoaCollection/ArraywithdifferenttypeobjectsyoucanspecifyaHinttoletDozerknowwhattypeofobjectsyouwantcreatedinthedestinationlist.IfaHintisnotspecifiedforthedestinationfield,thenthedestinationCollectionwillbepopulatedwithobjectsthatarethesametypeastheelementsinthesrcCollection.

<!--convertingTheFirstSubClassListtoTheFirstSubClassPrimeList--><field><a>hintList</a><b>hintList</b><b-hint>com.github.dozermapper.core.vo.TheFirstSubClassPrime</b-hint></field>

BelowisasummaryofthemappinglogicusedwhenmappingArrays,Sets,andLists.Thisgivesabreakdownofwhathappenswhenhintsareorarenotused.

ListtoList

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

ArraytoList

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

ListtoArray

CollectionsandArrays

43

Page 44: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destarraywillcontaindatatypesdefinedbythearray

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type(onlyifObjectArray)

ArraytoArray

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destarraywillcontaindatatypesdefinedbythearray

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type(onlyifObjectArray)

SettoSet

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

ArraytoSet

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

SettoArray

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destarraywillcontaindatatypesdefinedbythearray

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type(onlyifObjectArray)

ListtoSet

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

SettoList

**DestHintreq’d:NO

DestHintallowed:YES

Ifnodesthintspecified:Destlistwillcontainthesamedatatypesinthesource

Ifhintisspeficied:Destlistwillcontainobjectsthatmatchdesthint(s)type

CollectionsandArrays

44

Page 45: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

UsingJDK1.5GenericsforCollectionMappingHintsarenotrequiredwhenJDK1.5Genericsareused.ToconvertaCollection/ArraytoaCollection/Arraywithdifferenttypeobjectsdozercandetermineparameterizedtypesatruntime.

publicclassUserGroup{

privateSet<User>users;

publicSet<User>getUsers(){returnusers;}

publicvoidsetUsers(Set<User>aUsers){users=aUsers;}

}publicclassUserGroupPrime{

privateList<UserPrime>users;

publicList<UserPrime>getUsers(){returnusers;}

publicvoidsetUsers(List<UserPrime>aUsers){users=aUsers;}

}

ObjectArraytoList(bi-directional)

WhenconvertinganObjectarraytoaList,bydefaultthedestinationListwillcontainthesamedatatypeasthesourceArray.

<!--changinganInteger[]toListandbackagain--><field><a>arrayForLists</a><b>listForArray</b></field>

Useahintfordatatypeconversion.Becauseahintisspecified,thedestinationListwillcontainStringelementsinsteadofIntegers.

<!--changinganInteger[]toListandbackagain--><field><a>arrayForLists</a><b>listForArray</b><b-hint>java.lang.String</b-hint></field>

PrimitiveArraytoPrimitiveArray(bi-directional)

WhenconvertinganObjectarraytoanArray,bydefaultthedestinationArraywillcontainthesamedatatypeasthesourceArray.

<!--convertingint[]toint[]bynameonly-->

CollectionsandArrays

45

Page 46: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<field><a>anArray</a><b>theMappedArray</b></field>

Cumulativevs.Non-CumulativeListMapping(bi-directional)

IfyouaremappingtoaClasswhichhasalreadybeeninitialized,dozerwilleither'add'or'update'objectstoyourList.IfyourListorSetalreadyhasobjectsinitdozerchecksthemappedList,Set,orArrayandcallsthecontains()methodtodetermineifitneedsto'add'or'update'.Thisisdeterminedusingtherelationship-typeattributeonthefieldtag.Thedefaultis'cumulative'.relationship-typecanbespecifedatthefieldmapping,classmapping,orglobalconfigurationlevel.

globalconfigurationlevel….

<mappings><configuration><relationship-type>non-cumulative</relationship-type></configuration></mappings>

classmappinglevel….

<mappings><mappingrelationship-type="non-cumulative"><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><field><a>someList</a><b>someList</b></field></mapping></mappings>

fieldmappinglevel….

<!--objectswillalwaysbeaddedtoanexistingList--><fieldrelationship-type="cumulative"><a>hintList</a><b>hintList</b><a-hint>com.github.dozermapper.core.vo.TheFirstSubClass</a-hint><b-hint>com.github.dozermapper.core.vo.TheFirstSubClassPrime</b-hint></field>

<!--objectswillupdatedifalreadyexistinList,addediftheyarenotpresent--><fieldrelationship-type="non-cumulative"><a>unequalNamedList</a><b>theMappedUnequallyNamedList</b></field>

Note:ifyoudonotdefinecustomequals()andhashCode()methodsnon-cumulativeoptionwillnotfunctionproperly,asDozerwillfailtodetermineobjectequalityandwillrelyonJDKgeneratedobjectIds.Indefaultcasetwoinstancesofaclassarealwaystreatedasdifferentandupdatewillnotoccure.

RemovingOrphans

CollectionsandArrays

46

Page 47: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Orphansareelementswhichexistinadestinationcollectionthatdidnotexistwithinthesourcecollection.Dozerwillremoveorphansbycallingthe'remove'methodonactualorphansoftheunderlyingdestinationcollection;itwillnotclearall.Todetermineelementswhichareorphansdozerusesthecontains()methodtocheckiftheresultscontainsorphans.Thedefaultsettingvalueisfalse.

<!--orphanobjectswillalwaysberemovedfromanexistingdestinationList--><fieldremove-orphans="true"><a>srcList</a><b>destList</b></field>

CollectionsandArrays

47

Page 48: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MapBackedPropertyMapping

MaptoMap

Dozerwillmapajava.util.Maptoajava.util.Map.Iftherearecomplextypeswithhintsitwilldodeeprecursionmappingaswell.Ifthedestinationmapexistsitwilladdelementstotheexistingmap.

<mapping><class-a>com.github.dozermapper.core.vo.map.MapToMap</class-a><class-b>com.github.dozermapper.core.vo.map.MapToMapPrime</class-b><field><a>standardMapWithHint</a><b>standardMapWithHint</b><a-hint>com.github.dozermapper.core.vo.TestObject</a-hint><b-hint>com.github.dozermapper.core.vo.TestObjectPrime</b-hint></field></mapping>

MappingFieldLevelPropertiestoajava.util.MaporaCustomMapwithuniqueGet/Setmethods

Dozersupportsmappingmapbackedpropertiesatthefieldlevel.Themapcaneitherimplementthejava.util.MapInterfaceorbeacustommapwithasetofuniqueGet/Setmethods.

InthisexampleFieldAisabasicStringanditismappedtoFieldBwhichisaHashMap.ThekeyintheHashMapwillbe"stringProperty"(theattributename)andthevaluewillbewhatevervalueisstoredinthatattribute.

<mapping><class-a>com.github.dozermapper.core.vo.map.PropertyToMap</class-a><class-b>com.github.dozermapper.core.vo.map.MapToProperty</class-b><field><a>stringProperty</a><b>hashMap</b></field></mapping>

ThisexampleshowsFieldAisabasicStringanditismappedtoFieldBwhichisaHashMap.ThekeyintheHashMapwillbe"myStringProperty"andthevaluewillbewhatevervalueisstoredinthatattribute.AlsonoticethatFieldAhasauniquesetter()methodname.

<mapping><class-a>com.github.dozermapper.core.vo.map.PropertyToMap</class-a><class-b>com.github.dozermapper.core.vo.map.MapToProperty</class-b><field><aset-method="addStringProperty2">stringProperty2</a><bkey="myStringProperty">hashMap</b></field></mapping>

ThisexampleshowsFieldAisabasicStringanditismappedtoFieldBwhichisacustommap.Thekeyinthecustommapwillbe"myCustomProperty"andthevaluewillbewhatevervalueisstoredinthatattribute.NoticethatFieldBhasuniquemapgetter()andmapsetter()methodnames.IfyouareusingacustommapyoumustexplicitlysetthemapGet/Setmethodnames.AdestinationhintcanalsobeprovidedifyourcustommapimplementsanInterfaceorisanAbstractclass.

MapBackedPropertyMapping

48

Page 49: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<mapping><class-a>com.github.dozermapper.core.vo.map.PropertyToMap</class-a><class-b>com.github.dozermapper.core.vo.map.MapToProperty</class-b><field><a>stringProperty3</a><bmap-get-method="getValue"map-set-method="putValue"key="myCustomProperty">customMap</b></field><field><a>stringProperty4</a><bmap-get-method="getValue"map-set-method="putValue"key="myCustomNullProperty">nullCustomMap</b><b-hint>com.github.dozermapper.core.vo.map.CustomMap</b-hint></field><field><a>stringProperty5</a><bmap-get-method="getValue"map-set-method="putValue">customMap</b></field></mapping>

MappingClassLevelPropertiestoajava.util.MaporaCustomMapwithuniqueGet/Setmethods

Dozercanalsomapentirecomplexobjectsdirectlytoajava.util.Maporacustommapobject.Thisexampleshowsthedeclarationofamappingbetweenacomplexobject(PropertyToMap)andajava.util.Map.Whendoingthisyouneedtoexplicitlydefineauniquemap-idforthemapping.Thisisusedwhendeterminingwhichmaptouseatrun-time.EveryattributeonthePropertyToMapclasswillbemappedtothejava.util.Map.YouDONOTneedtoexplicitlydefinethesemappings.Fieldexcludemappingscanbeusedtoexcludefieldsatrun-time.Iftheattributenameisnotthesameasthemapkeyjustsetthekeyattributeforacustomfieldmapping.ThemappingtostringProperty2showsanexampleofthis.

Thesecondexampleshowshowtosetupacustommapobject.Theonlydifferencehereisthatyouneedtoexplicitlydefinemap-set-methodandmap-get-methodvalues.Thesecorrespondtothejava.util.Mapget()andput()methods.

<mappingmap-id="myTestMapping"><class-a>com.github.dozermapper.core.vo.map.PropertyToMap</class-a><class-b>java.util.Map</class-b><field><aset-method="addStringProperty2">stringProperty2</a><bkey="myStringProperty">this</b></field><field-exclude><a>excludeMe</a><b>this</b></field-exclude></mapping><mappingmap-id="myCustomTestMapping"><class-a>com.github.dozermapper.core.vo.map.PropertyToMap</class-a><class-bmap-set-method="putValue"map-get-method="getValue">com.github.dozermapper.core.vo.map.CustomMap</class-b><field><aset-method="addStringProperty2">stringProperty2</a><bkey="myStringProperty">this</b></field><field-exclude><a>excludeMe</a><b>this</b></field-exclude></mapping>

MapBackedPropertyMapping

49

Page 50: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Theexamplebelowshowshowtousethesemappings.Noticethatthefieldmappingsreferenceamap-id.ThefirstfieldmappingwillusethemyTestMappingdefinedmappingandmapaccordingly.Samegoeswiththecustommapping.

<mapping><class-a>com.github.dozermapper.core.vo.map.MapTestObject</class-a><class-b>com.github.dozermapper.core.vo.map.MapTestObjectPrime</class-b><fieldmap-id="myTestMapping"><a>propertyToMap</a><b>propertyToMapMap</b></field><fieldmap-id="myTestMapping"><a>propertyToMapToNullMap</a><b>nullPropertyToMapMap</b><b-hint>java.util.HashMap</b-hint></field><fieldmap-id="myCustomTestMapping"><a>propertyToCustomMap</a><b>propertyToCustomMapMap</b></field></mapping>

TheClassLevelmapbackedmappingscanalsobeusedasastandardmapping.ForthisdozerhasanewAPI.InadditiontothesourceanddestinationclassesyoucannowpassinthemapreferenceId.

//Example1PropertyToMapptm=newPropertyToMap();ptm.setStringProperty("stringPropertyValue");ptm.addStringProperty2("stringProperty2Value");Mapmap=Mapper.map(ptm,HashMap.class,"myTestMapping");

//Example2CustomMapcustomMap=mapper.map(ptm,CustomMap.class,"myCustomTestMapping");

//Example3CustomMapcustom=newCustomMap();custom.putValue("myKey","myValue");Mapper.map(ptm,custom,"myCustomTestMapping");

//Example4-MapBackMapmap=newHashMap();map.put("stringProperty","stringPropertyValue");PropertyToMapproperty=mapper.map(map,PropertyToMap.class,"myTestMapping");assertEquals("stringPropertyValue",property.getStringProperty());

MapBackedPropertyMapping

50

Page 51: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ProxyObjects

Overview

Dozersupportsmappingsdoneonproxyobjects.Thisistypicallythecasewhenusingpersistenceframework,whichsupportssophisticatedfeatureslikelazy-loading.Inthiscaseapplicationisworkingwithfakeobjects,containingtherealobjectsencapsulated.Implementationofproxiesisdependantonthetechnologyyouuse.Generallyspeaking,therearetwopopularlibrariesforcreatingJavaproxies(CglibandJavassist).However,howparticularframeworkmakesusesofthemcouldalsovary.Dozeroffersbydefaultagenericwaytohandlesimpleproxyscenarios,bothJavassistandCglib.Howeveritisstronglyrecommendedtotuneproxyhandlingbehaviorforyourparticularscenario.

Configuration

Proxyimplementationisset-upbymodifyingconfigurationfile.Currently,besidesofdefaultbehavior,HibernateandNo-Proxymodesaresupported.Forthefulllistoftheimplementations,seethelistofcom.github.dozermapper.core.util.DozerProxyResolverinterfaceimplementations.ThelistcouldberetrievedfromJavaDocs.

Incaseyoudonotmapproxiedobjects-useNoProxyresolver,whichimposesminimumperformanceoverhead.

CustomScenarios

Forcustomscenariositispossibletoprovideyourownimplementationofcom.github.dozermapper.core.util.DozerProxyResolverinterface.Itisconfiguredinthesamewayasthestandardclasses.

ProxyObjects

51

Page 52: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CustomConvertersCustomconvertersareusedtoperformcustommappingbetweentwoobjects.IntheConfigurationblock,youcanaddsomeXMLtotellDozertouseacustomconverterforcertainclassAandclassBtypes.WhenacustomconverterisspecifiedforaclassAandclassBcombination,Dozerwillinvokethecustomconvertertoperformthedatamappinginsteadofthestandardmappinglogic.

Yourcustomconvertermustimplementthecom.github.dozermapper.core.CustomConverterinterfaceinorderforDozertoacceptit.Otherwiseanexceptionwillbethrown.

Customconvertersaresharedacrossmappingfiles.ThismeansthatyoucandefinethemonceinamappingfileanditwillbeappliedtoallclassmappingsinothermappingfilesthatmatchtheClassA-ClassBpattern.Intheexamplebelow,wheneverDozercomesacrossamappingwherethesrc/destclassmatchthecustomconverterdefinition,itwillinvokethecustomconverterclassinsteadofperformingthetypicalmapping.

<?xmlversion="1.0"encoding="UTF-8"?><mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttp://dozermapper.github.io/schema/bean-mapping.xsd"><configuration><custom-converters><!--thesearealwaysbi-directional--><convertertype="com.github.dozermapper.core.converters.TestCustomConverter"><class-a>com.github.dozermapper.core.vo.CustomDoubleObject</class-a><class-b>java.lang.Double</class-b></converter><!--YouareresponsibleformappingeverythingbetweenClassAandClassB--><convertertype="com.github.dozermapper.core.converters.TestCustomHashMapConverter"><class-a>com.github.dozermapper.core.vo.TestCustomConverterHashMapObject</class-a><class-b>com.github.dozermapper.core.vo.TestCustomConverterHashMapPrimeObject</class-b></converter></custom-converters></configuration></mappings>

Customconverterscanalsobespecifiedattheindividualfieldlevel.Intheexamplebelow,Dozerwillinvokethecustomconvertertoperformthefieldmapping.

<mapping><class-a>com.github.dozermapper.core.vo.SimpleObj</class-a><class-b>com.github.dozermapper.core.vo.SimpleObjPrime2</class-b><fieldcustom-converter="com.github.dozermapper.core.converters.StringAppendCustomConverter"><a>field1</a><b>field1Prime</b></field></mapping>

Customconverter'instances'canbereusedattheindividualfieldlevel.Intheexamplebelow,Dozerwillinvokethecustomconvertertoperformthefieldmapping.

<mapping><class-a>com.github.dozermapper.core.vo.SimpleObj</class-a><class-b>com.github.dozermapper.core.vo.SimpleObjPrime2</class-b>

CustomConverters

52

Page 53: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<fieldcustom-converter-id="CustomConverterWithId"><a>field1</a><b>field1Prime</b></field></mapping>

CustomConverterinstancescanbeprovidedduringconfigurationofMapperviaDozerBeanMapperBuilder#withCustomConverter(..)method.

<?xmlversion="1.0"encoding="UTF-8"?><beansdefault-lazy-init="false"><beanid="com.github.dozermapper.core.Mapper"class="com.github.dozermapper.core.DozerBeanMapper"><propertyname="mappingFiles"><list><value>dozerBeanMapping.xml</value><value>injectedCustomConverter.xml</value></list></property><propertyname="customConvertersWithId"><map><entrykey="CustomConverterWithId"ref="configurableConverterBeanInstance1"/><entrykey="CustomConverterWithId2"ref="configurableConverterBeanInstance2"/></map></property></bean></beans>

Samplecustomconverterimplementation:

Note:CustomConvertersgetinvokedwhenthesourcevalueisnull,soyouneedtoexplicitlyhandlenullvaluesinyourcustomconverterimplementation.

importcom.github.dozermapper.core.CustomConverter;importcom.github.dozermapper.core.MappingException;

publicclassTestCustomConverterimplementsCustomConverter{

@OverridepublicObjectconvert(ObjectexistingDestinationFieldValue,ObjectsourceFieldValue,Class<?>destinationClass,Class<?>sourceClass){if(sourceFieldValue==null){returnnull;}

CustomDoubleObjectdest;if(sourceinstanceofDouble){//checktoseeiftheobjectalreadyexistsif(destination==null){dest=newCustomDoubleObject();}else{dest=(CustomDoubleObject)destination;}

dest.setTheDouble(((Double)source).doubleValue());

returndest;}elseif(sourceinstanceofCustomDoubleObject){doublesourceObj=((CustomDoubleObject)source).getTheDouble();returnnewDouble(sourceObj);}else{thrownewMappingException("ConverterTestCustomConverter"+"usedincorrectly.Argumentspassedinwere:"+destination+"and"+source);

CustomConverters

53

Page 54: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

}}}

CustomConverterscanalsobeinjectedintotheMapperifyouneedtodosomemanipulationwiththembeforetheyareusedindozer.

<?xmlversion="1.0"encoding="UTF-8"?><beansdefault-lazy-init="false"><beanid="com.github.dozermapper.core.Mapper"class="com.github.dozermapper.core.DozerBeanMapper"><propertyname="mappingFiles"><list><value>dozerBeanMapping.xml</value><value>injectedCustomConverter.xml</value></list></property><propertyname="customConverters"><list><refbean="customConverterTest"/></list></property></bean><!--customconverter--><beanid="customConverterTest"class="com.github.dozermapper.core.converters.InjectedCustomConverter"><propertyname="injectedName"><value>injectedName</value></property></bean></beans>

SupportforArrayTypes

YoucanspecifyacustomconverterforArraytypes.Forexample,ifyouwanttouseacustomconverterformappingbetweenanarrayofobjectsandaStringyouwouldusethefollowingmappingnotation.DozergenericallyusesClassLoader.loadClass()whenparsingthemappingfiles.Forarrays,javaexpectstheclassnameinthefollowingformat:[Lcom.github.dozermapper.core.vo.SimpleObj;

<convertertype="com.github.dozermapper.core.converters.StringAppendCustomConverter"><class-a>[Lcom.github.dozermapper.core.vo.SimpleObj;</class-a><class-b>java.lang.String</class-b></converter>

Supportforprimitives

Youcanspecifyacustomconverterforprimitivetypes.Justusetheprimitivewrapperclasswhendefiningthecustomconvertermapping.Inthefollowingexample,DozerwillusethespecifiedcustomconverterwhenmappingbetweenSomeObjectandtheintprimitivetype.NotethatDozerwillalsousethecustomconverterwhenmappingbetweenSomeObjectandtheIntegerwrappertype.

<convertertype="somePackage.SomeCustomConverter"><class-a>somePackage.SomeObject</class-a><class-b>java.lang.Integer</class-b></converter>

ConfigurableCustomConverters

CustomConverters

54

Page 55: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Youcandefineacustomconverter,whichcanbeconfiguredfrommappingsviaconfigurationparameter.InthiscaseyoushouldimplementConfigurableCustomConverterinterfaceinsteadofusualCustomConverter.Configurableconverterhasadditionalattributeprovidedinruntime-param.Parameterisprovidedusingcustom-converter-paramattribute.

<mapping><class-a>com.github.dozermapper.core.vo.BeanA</class-a><class-b>com.github.dozermapper.core.vo.BeanB</class-b><fieldcustom-converter="com.github.dozermapper.core.converters.MathOperationConverter"custom-converter-param="+"><a>amount</a><b>amount</b></field></mapping>

Configurablecustomconvertershouldbeusedwhenyouhavesimilarbehaviourinmanycases,whichcanbeparametrized,butthenumberofcombinationsistoohightodosimpleCustomConvertersubclassing.

importcom.github.dozermapper.core.ConfigurableCustomConverter;importcom.github.dozermapper.core.MappingException;

publicclassMathOperationConverterimplementsConfigurableCustomConverter{

privateStringparameter;

@OverridepublicvoidsetParameter(Stringparameter){this.parameter=parameter;}

@OverridepublicObjectconvert(ObjectexistingDestinationFieldValue,ObjectsourceFieldValue,Class<?>destinationClass,Class<?>sourceClass){Integersource=(Integer)sourceFieldValue;Integerdestination=(Integer)existingDestinationFieldValue;

if("+".equals(parameter)){returndestination.intValue+source.intValue();}

if("-".equals(parameter)){returndestination.intValue-source.intValue();}

thrownewMappingException("ConverterMathOperationConverter"+"usedincorrectly.Argumentspassedinwere:"+destination+","+source+"and"+parameter);}}

NewCustomConverterAPI

WhileprovidinggreatdealofflexibilityCustomConverterAPIdescribedaboveiswrittenonfairlylowlevelofabstraction.Thisresultsinconverter,whichcodeisdifficulttounderstandandtoreuseinotherwaysthanpluggingintoDozermapping.Howeveritisnotuncommonsituationwhenthesameconversionlogicshouldbecalledfromaplaceotherthanbeanmappingframework.versionofDozergetsshippedwithnew-cleanerAPIfordefiningcustomconverter,whichgivesyoumoreobviousAPIwhiletakingawaycertainpartofcontroloftheexecutionsflow.Thefollowingexampledemonstratessimple,yetworkingconverterusingnewAPI.

CustomConverters

55

Page 56: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

importcom.github.dozermapper.core.DozerConverter;

publicclassNewDozerConverterextendsDozerConverter<String,Boolean>{

publicNewDozerConverter(){super(String.class,Boolean.class);}

@OverridepublicBooleanconvertTo(Stringsource,Booleandestination){if("yes".equals(source)){returnBoolean.TRUE;}elseif("no".equals(source)){returnBoolean.FALSE;}thrownewIllegalStateException("Unknownvalue!");}

@OverridepublicStringconvertFrom(Booleansource,Stringdestination){if(Boolean.TRUE.equals(source)){return"yes";}elseif(Boolean.FALSE.equals(source)){return"no";}thrownewIllegalStateException("Unknownvalue!");}}

NotethatJava5Genericsaresupportedandyoudonotneedtocastsourceobjecttodesiredtypeaspreviously.

DataStructureConversions

Therearecaseswhereitisrequiredtoperformprogrammaticdatastructureconversion,saycopyeachoddelementinalistasmapkey,buteachevenasmapvalue.InthiscaseitisneededtodefinetransformationofthestructurewhilerelyingonusualDozermappingsupportforindividualvalues.ForthispurposesitispossibletouseMapperAwareinterface,whichinjectscurrentmapperinstanceinsidecustomconverter.

importjava.util.HashMap;importjava.util.List;importjava.util.Map;

importcom.github.dozermapper.core.DozerConverter;importcom.github.dozermapper.core.Mapper;importcom.github.dozermapper.core.MapperAware;

publicclassConverterextendsDozerConverter<List,Map>implementsMapperAware{

privateMappermapper;

publicConverter(){super(List.class,Map.class);}

@OverridepublicvoidsetMapper(Mappermapper){this.mapper=mapper;}

@OverridepublicMapconvertTo(Listsource,Mapdestination){MaporiginalToMapped=newHashMap();for(Sourceitem:source){TargetmappedItem=mapper.map(item,Target.class);

CustomConverters

56

Page 57: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

originalToMapped.put(item,mappedItem);}returnoriginalToMapped;}

@OverridepublicListconvertFrom(Mapsource,Listdestination){thrownewIllegalStateException("Notimplemented");}}

CustomConverters

57

Page 58: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CustomBeanFactoriesYoucanconfigureDozertousecustombeanfactoriestocreatenewinstancesofdestinationdataobjectsduringthemappingprocess.BydefaultDozerjustcreatesanewinstanceofanydestinationobjectsusingadefaultconstructor.Thisissufficientformostusecases,butifyouneedmoreflexibilityyoucanspecifyyourownbeanfactoriestoinstantiatethedataobjects.

Yourcustombeanfactorymustimplementthecom.github.dozermapper.core.BeanFactoryinterface.BydefaulttheDozermappingenginewillusethedestinationobjectclassnameforthebeanidwhencallingthefactory.

publicinterfaceBeanFactory{publicObjectcreateBean(Objectsource,ClasssourceClass,StringtargetBeanId,BeanContainerbeanContainer);}

Next,inyourDozermappingfile(s)youjustneedtospecifyabean-factoryxmlattributeforanymappingsthatyouwanttouseacustomfactory.

Inthefollowingexample,theSampleCustomBeanFactorywillbeusedtocreateanynewinstancesoftheInsideTestObjectPrimejavabeandataobject.

<mapping><class-a>com.example.vo.InsideTestObject</class-a><class-bbean-factory="com.example.factories.SomeCustomBeanFactory">com.example.vo.InsideTestObjectPrime</class-b></mapping>

Ifyourfactorylooksupbeansbasedonadifferentidthanclassname,youcanspecifyafactory-bean-idxmlattribute.Atruntimethespecifiedfactory-bean-idwillbepassedtothefactoryinsteadofclassname.

<mapping><class-a>com.example.vo.InsideTestObject</class-a><class-bbean-factory="com.example.factories.SomeCustomBeanFactory"factory-bean-id="someBeanLookupId">com.example.vo.InsideTestObjectPrime</class-b></mapping>

SpecifyingDefaultFactories

Alternatively,beanfactoriescanbespecifiedinthedefaultconfigurationsectionofanyDozermappingfile(s).Thedefaultfactorywouldbeusedforanymappingsinthatfile.

<configuration><stop-on-errors>true</stop-on-errors><wildcard>true</wildcard><bean-factory>com.example.factories.SomeDefaultBeanFactory</bean-factory></configuration>

Beanfactoriescanalsobespecifiedatthemappinglevel.Thespecifiedfactorywouldbeusedforclass-aandclass-b.

<mappingbean-factory="com.example.factories.SomeCustomBeanFactory"><class-a>com.example.vo.TestObject</class-a>

CustomBeanFactories

58

Page 59: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<class-b>com.example.vo.TestObjectPrime</class-b></mapping>

Springbeanfactoryinjection

BeanfactoriescanbeinjectedviaSpringorsimilarinversionofcontroltechniques.

<beans><beanid="com.github.dozermapper.core.Mapper"class="com.github.dozermapper.core.DozerBeanMapper"><propertyname="mappingFiles"><list><value>dozerBeanMapping.xml</value></list></property><propertyname="factories"><map><!--thekeymatchesthenameofthefactoryinthedozerBeanMapping.xmlfile--><entrykey="com.github.dozermapper.core.factories.SampleCustomBeanFactory"><refbean="sampleCustomBeanFactory"/></entry><!--morefactoriescanbesuppliedwithadditionalentry's--></map></property></bean><beanid="sampleCustomBeanFactory"class="com.github.dozermapper.core.factories.SampleCustomBeanFactory"/></beans>

BydefiningyourfactoriesasSpringbeansyoucantheninjectthemintotheMapperinstance.

CustomBeanFactories

59

Page 60: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CustomCreateMethodsYoucanconfigureDozertousecustomstaticcreatemethodstocreatenewinstancesofdestinationdataobjectsduringthemappingprocess.Thiscaneitherbesetatthefieldlevelorclasslevel.

<mapping><class-acreate-method="someCreateMethod">com.github.dozermapper.core.vo.InsideTestObject</class-a><class-b>com.github.dozermapper.core.vo.InsideTestObjectPrime</class-b><field><a>label</a><b>labelPrime</b></field></mapping>

SpecifyingacustomcreatemethodattheFieldlevel….

<mapping><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-b>com.github.dozermapper.core.vo.TestObjectPrime</class-b><field><a>createMethodType</a><bcreate-method="someCreateMethod">createMethodType</b></field></mapping>

Itisalsopossibletoreferencedifferentclasswithstaticfactorymethod.Thisisdonebyprovidingfullyqualifiedtypenameandmethodnameseparatedbydot.

<bcreate-method="com.github.dozermapper.core.factory.Factory.create">field</b>

CustomCreateMethods

60

Page 61: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Customget()set()Methods

Mappingafieldwithnoget()orset()methods

Usetheattributeis-accessibletodeclarethatthefieldcanbeaccesseddirectly.Dozerisabletoaccessprivatepropertiesthatdonothavegetterorsettermethods.

<field><a>fieldAccessible</a><bis-accessible="true">fieldAccessible</b></field>

CustomSet()andGet()methods(bi-directional)

Forthosebeansthatmighthaveunorthodoxgetterandsettermethods,Dozersupportuserspecifiedsetterandgettermethods.Tomakeabi-directionalmappinginthiscase,lookatthefollowingexamplebelow.ThesourcefieldinelementAspecifiesacustomsettermethodandgettermethodusingattributes.

<field><aset-method="placeValue"get-method="buildValue">value</a><b>value</b></field>

InthiscasewearemappingaStringtoanArrayListbycallingtheaddIntegerToList()method.Notethatthisisdefinedasaone-wayfieldtypesincewecannotmapanArrayListtoaString.

<!--wecannotmapaArrayListtoaString,hencetheone-waymapping--><fieldtype="one-way"><a>integerStr</a><bset-method="addIntegerToList">integerList</b></field>

OverloadedSet()methods(bi-directional)

Sometimesset()methodscanbeoverloaded.Inordertochosethecorrectoneyoucanaddtheclasstypeasaparameter.

<field><a>overloadGetField</a><bset-method="setOverloadSetField(java.util.Date)">overloadSetField</b></field>

IterateMethodMapping(bi-directional)

Dozeralsosupportsiteratemethodlevelmapping.InthefollowingexampletheListappleComputerswillbeiteratedthroughandforeachobjectthemethodaddComptuerwillbecalled.Anyfieldthatisdenotedastype=iteraterequiresahint.Theget()methodcanreturnanArray,List,orIterator.

<field><a>appleComputers</a><bset-method="addComputer"type="iterate">computers</b>

Customget()set()Methods

61

Page 62: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<b-hint>com.github.dozermapper.core.vo.AppleComputer</b-hint></field>

Belowisanexamplewithiteratemethodsonbothfields.

<field><aset-method="addCar"get-method="myIterateCars"type="iterate">iterateCars</a><bset-method="addIterateCar"type="iterate">iterateCars</b><a-hint>com.github.dozermapper.core.vo.Car</a-hint><b-hint>com.github.dozermapper.core.vo.Car</b-hint></field>

Customget()set()Methods

62

Page 63: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ExpressionLanguage

Usage

Dozerprovidesoptionalsupportforstandardjavaexpressionlanguage(javax.el).

Currentsupportforexpressionsisstart-uptimeonly.Expressionsarenotresolvedduringeachmapping,butratherduringmappingloadingtime.EachattributeornodevaluecancontainavalidELexpression${}.

DozersupportsanyELimplementationwrittenagainstjavax.elstandardAPI.Functionalityistestedwith'glassfish'internally,butotherELprovidersshouldworkaswell.

Youcandefineglobalvariablesforthemapperinvariablesconfigurationblock.

<configuration><wildcard>true</wildcard><variables><variablename="type_name">com.github.dozermapper.core.sample.MyType</variable></variables></configuration><mapping><class-a>${type_name}</class-a><class-b>com.github.dozermapper.core.sample.OtherType</class-b></mapping>

Enabling

ELsupportisanoptionalfeature.Toenableit,youmustaddthebelowdependenciestoyourclasspath:

<dependency><groupId>javax.el</groupId><artifactId>javax.el-api</artifactId><version>3.0.0</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId><version>3.0.0</version></dependency>

ItisthisenabledontheMapperbythebelowfluentconstruct:

Mappermapper=DozerBeanMapperBuilder.create().withMappingFiles(mappingFiles).withELEngine(newDefaultELEngine()).build();

ExpressionLanguage

63

Page 64: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

LoggingTheloggingfacadeframeworkinDozerisSLF4J.ItreplacedCommonsLogging,whichwasusedinprojectpreviouslyuntilversion5.3.

PleaserefertoSLF4JDocumentationformoreinformationonsettingupandconfiguringdifferentloggingimplementations.

Logging

64

Page 65: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

EventListeningByimplementingtheEventListenerinterfacedozerallowsyoutolistento4differentevents:

mappingStarted

mappingFinished

preWritingDestinationValue

postWritingDestinationValue

AnEventobjectispassedintothesecallbackmethodswhichstoresinformationabouttheClassMap,FieldMap,sourceobject,destinationobject,anddestinationvalue.ThiswillallowyoutoextendDozerandmanipulatemappedobjectsatrun-time.Theinterfaceisshownbelow:

publicinterfaceEventListener{

publicvoidonMappingStarted(Eventevent);

publicvoidonPreWritingDestinationValue(Eventevent);

publicvoidonPostWritingDestinationValue(Eventevent);

publicvoidonMappingFinished(Eventevent);}

ThelistenersthatyoucreatecanbeinjectedintotheMapperusinganIOClikeSpringorsetdirectlyduringMapperinstanceconfigurationusingDozerBeanMapperBuilder#withEventListener(..)method.BelowisanexampleusingSpringtoinjectaneventlistener:

<?xmlversion="1.0"encoding="UTF-8"?><beansdefault-lazy-init="false"><beanid="EventMapper"class="com.github.dozermapper.core.DozerBeanMapper"><propertyname="mappingFiles"><list><value>dozerBeanMapping.xml</value></list></property><propertyname="eventListeners"><list><refbean="eventTestListener"/></list></property></bean><beanid="eventTestListener"class="com.github.dozermapper.core.event.EventTestListener"/></beans>

EventListening

65

Page 66: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

QueryingmappingmetadataThissectionwillcoverthemappingmetadatainterface.Itprovideseasytouseread-onlyaccesstoallimportantpropertiesoraspectsofthecurrentlyactivemappingdefinitions.

Thefollowingsectionswillgivesomecodeexampleshowtousethemappingqueryinterfaces.Themostimportantinterfaceinthewholeprocessiscom.github.dozermapper.core.metadata.MappingMetadata.AninstancecanbeacquiredbycallingthegetMappingMetadata()methodoftheMapperinstance.

Considerthefollowingmappingfile:

<?xmlversion="1.0"encoding="UTF-8"?><mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttp://dozermapper.github.io/schema/bean-mapping.xsd"><mapping><class-a>com.github.dozermapper.core.vo.ClassA</class-a><class-b>com.github.dozermapper.core.vo.ClassB</class-b><field><a>fieldA</a><b>fieldB</b></field></mapping></mappings>

Tobeginqueryingthemappingdefinitionsthefollowingcodeisneeded:

Mappermapper=DozerBeanMapperBuilder.create().withMappingFiles(listOfFiles).build();MappingMetadatamapMetadata=mapper.getMappingMetadata();

NowthatareferencetoMappingMetadataisobtainedwecanstartqueryingforacertainclassmappingdefinition:

try{ClassMappingMetadataclassMappingMetadata=mapMetadata.getClassMapping(ClassA.class,ClassB.class);}catch(MetadataLookupExceptione){//couldn'tfindit}

WhenholdingareferencetoaClassMappingMetadatainterface,queriesforindividualfieldmappingscanbeexecuted:

try{FieldMappingMetadatafieldMetadata=classMetadata.getFieldMappingBySource("fieldA");//Destination:fieldBSystem.out.println("Destination:"+fieldMetadata.getDestinationName());}catch(MetadataLookupExceptione){//couldn'tfindit}

ForextensivedocumentationonthedifferentinterfacespleaserefertotheJavaDoc.

MetadataQueryInterface

66

Page 67: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

MetadataQueryInterface

67

Page 68: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

SpringFrameworkIntegrationWeprovidethedozer-spring4forintegratingspringapplication.IfyouareusingApacheMaven,simplycopy-pastethisdependencytoyourproject.

pom.xml

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>{dozer-version}</version></dependency><dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring4</artifactId><version>{dozer-version}</version></dependency>

Configuration

AddtheDozerBeanMapperFactoryBeantoyourSpringconfigurationfile.ThemappingFilespropertyiswhereyoushouldspecifyanycustomdozermappingfilesthatyouhavecreated.Thislistcanbeemptyifyoudon’thaveanycustommappings.Itisalsopossibletosetcustomeventlistenersandbeanfactories.

Important

YoushoulddefinetheDozermapperbeanisdefinedassingleton="true".YoushouldconfiguretheMapperinstance(s)thiswaysothatyoudonothavetoreloadandreinitializethemappingfilesforeachindividualmappingduringthelifecycleofyourapp.Reinitializingthemappingfilesforeachmappingwouldbeinefficientandunnecessary.TheDozerBeanMapperclassisthreadsafe.

XMLbasedconfiguration

NotethatthisFactoryBeansupportsSpringResources,whichmeansthatyoucouldloadmappingXmlfilesbyclasspathmaskforexample.

<beanid="dozerMapper"class="com.github.dozermapper.spring.DozerBeanMapperFactoryBean"><propertyname="mappingFiles"value="classpath*:/*mapping.xml"/><propertyname="customConverters"><list><beanclass="com.github.dozermapper.core.converters.CustomConverter"/></list></property><propertyname="eventListeners"><list><beanclass="com.github.dozermapper.core.listeners.EventListener"/></list></property><propertyname="factories"><map><entrykey="id"value-ref="bean-factory-ref"/></map></property></bean>

Alternatively,youcandefinetheDozerBeanMapperusingthedozernamespaceasfollow:

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dozer="http://dozermapper.github.io/schema/dozer-spring"

SpringIntegration

68

Page 69: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://dozermapper.github.io/schema/dozer-springhttps://dozermapper.github.io/schema/dozer-spring.xsd">

<dozer:mapperid="dozerMapper"/>

</beans>

Javabasedconfiguration

WhenusingJavaconfiguration,beandefinitionisasfollows:

@ConfigurationpublicclassDozerConfig{@BeanpublicDozerBeanMapperFactoryBeandozerMapper(ResourcePatternResolverresourcePatternResolver)throwsIOException{DozerBeanMapperFactoryBeanfactoryBean=newDozerBeanMapperFactoryBean();factoryBean.setMappingFiles(resourcePatternResolver.getResources("classpath*:/*mapping.xml"));//...returnfactoryBean;}}

Howtouseinyourapplication

UsingSpringtoretrievetheDozerMapper……

Look-upbasedusage

YoucanusetheDozerMapperthatlookedupfromtheSpringApplicationContext(BeanFactory).

MapperdozerMapper=applicationContext.getBean("dozerMapper",Mapper.class);DestinationObjectdestObject=dozerMapper.map(sourceObject,DestinationObject.class);

Injectionbasedusage

Alternatively,youcanusetheDozerMapperthatinjectedtoyourcomponentbySpringDIcontainer.

@ComponentpublicclassYourComponent{privatefinalMapperdozerMapper;publicYourComponent(MapperdozerMapper){this.dozerMapper=dozerMapper;}publicvoidanyMethod(){//...DestinationObjectdestObject=dozerMapper.map(sourceObject,DestinationObject.class);//...}}

HowtouseinSpringBootApplication

PleaseseeSpringBootIntegrationsection.

SpringIntegration

69

Page 70: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

SpringIntegration

70

Page 71: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

SpringBootIntegrationWeprovidethedozer-spring-boot-starterforintegratingspringbootapplicationsince6.2.0.IfyouareusingApacheMaven,simplycopy-pastethisdependencytoyourproject.

Note FordetailsforSpringFramewrokIntegration,pleaseseehere.

pom.xml

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring-boot-starter</artifactId><version>{dozer-version}</version></dependency>

Youcanspecifyanycustomdozermappingfilesinyourapplicationpropertiesoryml.

application.properties

dozer.mapping-files=classpath*:/*mapping.xml

application.yml

dozer:mapping-files:classpath*:/*mapping.xml

SpringBootIntegration

71

Page 72: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

3rdPartyObjectFactoriesDozersupportsmappingofplainJavaobjectstoframeworksthatrequireinstantiationofobjectsviacertainconventionofcallingfactorymethods.Toreproducetheexpectedbehaviorcustombeanfactoriesshouldbeused.

MappingJAXBObjects

DozerhassupportformappingPOJOstoJAXBobjects.UsetheJAXBBeanFactoryforanyJAXBobjectsyouwantcreate.

<mapping><class-a>com.github.dozermapper.core.vo.TestObject</class-a><class-bbean-factory="com.github.dozermapper.core.factory.JAXBBeanFactory">com.github.dozermapper.core.vo.jaxb.employee.Employee</class-b><field><a>name</a><b>firstName</b></field><field><a>street</a><b>address.street</b></field></mapping>

JAXB

72

Page 73: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

FrequentlyAskedQuestions

Common

Whattypesofdataobjectsaresupported?

WillDozerautomaticallyperformdatatypeconversions?

DoesDozerautomaticallymapfieldswithmatchingpropertynames?

IsDozerrecursive?

Willthegetterandsettermethodsbeinvokedwhenfieldsaremapped?

AreCollectionsandArrayssupported?

AreMaptypeobjects(i.eHashMap)supported?

Areabstractclasses,inheritance,andinterfacemappingsupported?

CanDozerbeconfiguredviaSpring?

WhichtypesofdatamappingsdoIneedacustomxmlmappingdefinitionfor?

Ifmysrcanddestobjecthaveallmatchingattributenames,doIneedtospecifyanyxmlmappingdefinitionsatall?

Formappingsthatrequireanxmlmappingdefinition,isthemappingdefinitionbi-directional,ordoIneed2xmldefinitionsifIneedtomapthetwoobjectsbothways?

Howarethecustomxmlmappingfilesloaded?

CanIloadamappingfilethatisnotintheclasspath?

HowcanItellifDozerisinitializingcorrectlyandloadingmyxmlmappingfiles?

HowdoesDozerperform?

WhichJDKversionsaresupported?

IsDozerinthemavenrepository?

IsDozergoodfortheenvironment?

Advanced

CanIimplementcustommappinglogicbetween2datatypesandhaveDozerinvokethiscustomlogicwhenit’sperformingmappings?

CanImaponefieldintoanotherfieldthatisnestednlayersdeepinthedestinationobject?

HowdoImapmultiplefieldstoasinglefield?

IfIammappingdataobjectsthathavebi-directionalrelationships,willitresultinaninfiniteloopandeventualstackoverflowerror?

HowdoImapanobjectcontainedinacollectiontoafield?

HowdoImapaComplexobjecttoaHashMapandviceversa?

HowdoImapfieldsthatdon’thavecorrespondinggetter/settermethods?

FAQ

73

Page 74: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Someofmydataobjectsdon’thavepublicconstructors.DoesDozersupportthisusecase?

DoesDozersupportJDK1.5enums?

DoesDozersupportJAXBgenerateddataobjects?

IsthereanEclipsepluginorvisualeditorforDozer?

Whenmappingcollections,howdoItellDozerwhattypeofdataobjectsIwantinthedestinationcollection?

HowcanItellDozertobypassmappingnulloremptystringvalues?

Tips,Tricks,andSuggestions

ShouldIencapsulatelogicthatcopiesdatabetweenobjects?

ShouldIwriteunittestsfordatamappinglogicthatIuseDozertoperform?

ShouldtheDozermapperbeconfiguredasaSingleton?

Isitbettertohave1largexmlmappingfileortohavemultiplesmallermappingfiles?

WhatarethebestwaystodebugDozer?

Whatisthebestwaytosetuptheglobalconfiguration?

Whatisthebestwaytosubmitabug,featurerequest,orpatch?

Answers

Whattypesofdataobjectsaresupported?

Dozerusesreflectiontoaccessdataobjectproperties,soitisdesignedtoworkwithdataobjectsthathavecorrespondinggetterandsettermethodsforitsfields.Forexample,adataobjectthathasafieldnamed"message"shouldhavegetMessageandsetMessagemethods.Dataobjectsthatdon’tfollowthispatternarealsosupported,butwillmostlikelyrequireacustommappingdefinition.Fortheseunorthodoxdataobjects,youcantellDozertodirectlyaccessfields(includingprivate)and/orexplicitlyspecifywhichget/setmethodstouse.

WillDozerautomaticallyperformdatatypeconversions?

Yes.Mostscenariosaresupportedoutofthebox.Theseincludeprimitives,JavaWrapperObjects,Numbersubclasses,Dates,Calendar,Collections,Arrays,Maps,andComplextypes

DoesDozerautomaticallymapfieldswithmatchingpropertynames?

Yes.Allfieldswithmatchingpropertynamesareimplicitlymapped.Itwouldbeatypicalusage,butyoucouldsuppressthisbehaviorbysettingwilcard="false".

IsDozerrecursive?

Yes.Dozerrecursivelymapstheentireobjectgraphforallfields.

Willthegetterandsettermethodsbeinvokedwhenfieldsaremapped?

Yes.Youcanbypassthisdefaultbehaviorbyexplicitlyspecifyingis-accessible="true"foranyofyourmappings.Ifis-accessibleisspecified,thefield(includingprivatefields)isaccesseddirectlyandthegetter/settermethodsarebypassed.Itisnotrecommendedthatyousetis-accessible="true",unlessyouaredealingwithanunorthodoxdata

FAQ

74

Page 75: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

objectthatdoesnotcontainanygetterorsettermethods.

AreCollectionsandArrayssupported?

Yes.Dozerautomaticallymapsbetweencollectiontypesandautomaticallyperformsanytypeconversion.

AreMaptypeobjects(i.eHashMap)supported?

Yes.AllJavaMapdatatypesaresupportedinadditiontoanyCustommapdatatypes.

Areabstractclasses,inheritance,andinterfacemappingsupported?

Yes.

CanDozerbeconfiguredviaSpring?

Yes.RefertoSpringIntegrationsectionofthedocumentation.

WhichtypesofdatamappingsdoIneedacustomxmlmappingdefinitionfor?

Onlyfieldsthatcan’tbeimplicitlymappedbymatchingonfieldname,needacustomxmlmappingdefinition.Ideally,thevastmajorityofyourfieldmappingscanbeperformedautomaticallyandonlythefewexceptionalcaseswillneedanexplicitfieldmappinginthexmlmappingfile.

Ifmysrcanddestobjecthaveallmatchingattributenames,doIneedtospecifyanyxmlmappingdefinitionsatall?

Nope.Justinvokethemapper.Youdon’tneedanyexplicitxmlmappingentriesforthiscombinationofsourceanddestinationobject.

Formappingsthatrequireanxmlmappingdefinition,isthemappingdefinitionbi-directional,ordoIneed2xmldefinitionsifIneedtomapthetwoobjectsbothways?

Allmappingdefinitionsarebi-directional,soyouonlyneedonemappingdefinition.Youcanmapa-→bandb-→ausingthissinglemappingdefinition.

Howarethecustomxmlmappingfilesloaded?

Dozerwillsearchtheentireclasspathlookingforthespecifiedfile(s).

CanIloadamappingfilethatisnotintheclasspath?

Yes,youcanloadfilesfromoutsidetheclasspathbyprepending"file:"totheresourcename.Ex)"file:c:\somedozermapping.xml"

HowcanItellifDozerisinitializingcorrectlyandloadingmyxmlmappingfiles?

Setthe-Ddozer.debugsystemproperty.Ifthisisset,DozerinitializationinformationisalsosenttoSystem.out.Ifyouarefamiliarwithlog4j,thisissimilartothe-Dlog4j.debugsystemproperty

FAQ

75

Page 76: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

HowdoesDozerperform?

WebelieveDozerperformsverywellandperformanceisahighpriorityforus.Wehavespentasignificantamountoftimeprofilingthecodeandoptimizingbottlenecks.

Performanceisgoingtodependonthecomplexityoftheusecaseandthenumberoffieldsmapped.Inourperformancetestsfor"average"mappingscenarios,theclassmappingtimesvaryfrom1/8ofamillisecondto2milliseconds.Thisroughlyequatesto50-450fieldmappingspermillisecond.However,thenumberofvariablesinanydecentbenchmarkmakesitalmostimpossibletotransfertheseresultsintoreasonableconclusionsabouttheperformanceofyourownapplication.Yourapplicationisdifferentandyouwillhaveuniqueusecases.

Dozerhasbeensuccessfullyimplementedonlarge,veryhightransactionalenterprisesystems,withoutanyresultingperformanceissues.Butwealwaysrecommendthatyourunperformancetestsonyourapplicationtodeterminetheactualperformancecostswithinyoursystem.Youcandecideforyourselfwhetherthosecostsareacceptableinthecontextoftheentiresystem.

WhichJDKversionsaresupported?

JDK1.8andabove.

IsDozerinthemavenrepository?

YesandwewillcontinuetodoourbesttogetfuturereleasesofDozeruploadedintotherepository.

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>{dozer-version}</version></dependency>

IsDozergoodfortheenvironment?

Yes,dozerdoesnotburnanyfossilfuelsandiswithintheEPA’srecommendedemissions.

CanIimplementcustommappinglogicbetween2datatypesandhaveDozerinvokethiscustomlogicwhenit’sperformingmappings?

Yes.AveryusefulfeatureprovidedbyDozeristheconceptofcustomconverters.Customconvertersareusedtoperformcustommappingbetweentwoobjects.IntheConfigurationblock,youcanaddsomeXMLtotellDozertouseacustomconverterforcertainclassAandclassBtypes.WhenacustomconverterisspecifiedforaclassAandclassBcombination,Dozerwillinvokethecustomconvertertoperformthedatamappinginsteadofthestandardmappinglogic.

<custom-converters><convertertype="com.github.dozermapper.core.converters.SomeCustomConverter"><class-a>com.github.dozermapper.core.vo.SomeCustomDoubleObject</class-a><class-b>java.lang.Double</class-b></converter></custom-converters>

CanImaponefieldintoanotherfieldthatisnestednlayersdeepinthedestinationobject?

Yes.Dozersupportsdotnotationfornestedfields.Aswithotherdozerfieldmappings,thesearebi-directional.

FAQ

76

Page 77: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<field><a>someNestedObj.someOtherNestedObj.someField</a><b>someOtherField</b></field>

HowdoImapmultiplefieldstoasinglefield?

Dozerdoesn’tcurrentlysupportthis.Andbecauseofthecomplexitiesaroundimplementingit,thisfeatureisnotcurrentlyontheroadmap.Apossiblesolutionwouldbetowrapthemultiplefieldsinacustomcomplextypeandthendefineacustomconverterformappingbetweenthecomplextypeandthesinglefield.Thisway,youcouldhandlethecustomlogicrequiredtomapthethreefieldsintothesingleonewithinthecustomconverter.

IfIammappingdataobjectsthatcontainbi-directionalrelationships,willitresultinaninfiniteloopandeventualstackoverflowerror?

No.Dozerhasbuiltinlogicthatpreventsinfiniteloopsforbi-directionaldataobjectrelationships

HowdoImapanobjectcontainedinacollectiontoafield?

Youwoulduseindexedbasedmapping.

<field><a>usernames[0]</a><b>username1</b></field>

HowdoImapaComplexobjecttoaHashMapandviceversa?

Youcanmapentirecomplexobjectsdirectlytoajava.util.Mapandviceversa.Whendoingthisyouneedtoexplicitlydefineauniquemap-idforthemapping.Thisisusedwhendeterminingwhichmaptouseatrun-time.Everyattributeonthecomplextypewillbemappedtothejava.util.Map.YouDONOTneedtoexplicitlydefinethesemappings.Iftheattributenameisnotthesameasthemapkeyjustsetthekeyattributeforacustomfieldmapping.

<mappingmap-id="myTestMapping"><class-a>com.github.dozermapper.core.vo.map.SomeComplexType</class-a><class-b>java.util.Map</class-b><field><a>stringProperty2</a><bkey="myStringProperty">this</b></field></mapping>

HowdoImapfieldsthatdon’thavecorrespondinggetter/settermethods?

YoucantellDozertodirectlyaccessfields(includingprivatefields)byspecifyingis-accessible="true"

<field><a>fieldA</a><bis-accessible="true">fieldB</b></field>

Someofmydataobjectsdon’thavepublicconstructors.DoesDozersupportthisusecase?

FAQ

77

Page 78: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Yes.Whencreatinganewinstanceofthedestinationobjectifapublicno-argconstructorisnotfound,Dozerwillautodetectaprivateconstructorandusethat.Ifthedataobjectdoesnothaveaprivateconstructor,youcanspecifyacustomBeanFactoryforcreatingnewinstancesofthedestinationobject.

DoesDozersupportJDK1.5enums?

Yes.EnumtoEnummappingisautomaticallyhandled.

DoesDozersupportJAXBgenerateddataobjects?

DozerhassupportformappingPOJOstoJAXBobjects.UsetheJAXBBeanFactoryforanyJAXBobjectsyouwantcreated.

IsthereanEclipsepluginorvisualeditorforDozer?

No,butwethinkitwouldbeagreataddition.Itwouldbeverypowerfultobeabletographicallymap2objectsandhavethecustomxmldefinitionsautogenerated,alongwithbeingabletovisuallyviewamappingdefinition.Ifanyonehasexpertiseincreatingeclipsepluginsandisinterestedonworkingonthisfeature,pleaseletusknow!

Whenmappingcollections,howdoItellDozerwhattypeofdataobjectsIwantinthedestinationcollection?

Hintsaresupportedtohandlethisusecase.HintsarenotrequiredifyouareusingJDK1.5GenericsbecausethetypescanbeautodetectedbyDozer.Butifyouarenotusinggenerics,toconvertaCollection/ArraytoaCollection/ArraywithdifferenttypeobjectsyoucanspecifyaHinttoletDozerknowwhattypeofobjectsyouwantcreatedinthedestinationlist.IfaHintisnotspecifiedforthedestinationfield,thenthedestinationCollectionwillbepopulatedwithobjectsthatarethesametypeastheelementsinthesrcCollection.

<field><a>someList</a><b>otherList</b><b-hint>com.github.dozermapper.core.vo.TheFirstSubClassPrime</b-hint></field>

HowcanItellDozertobypassmappingnulloremptystringvalues?

Youcanbypassthemappingofnullvaluesbyspecifyingmap-null="false".Ifthisisspecified,thedestfieldmappingisbypassedatruntimeandthedestinationvaluesettermethodwillnotbecalledifthesrcvalueisnull.Thiscanbespecifiedatthemappingorclasslevel.

YoucanbypassthemappingofemptyStringvaluesbyspecifyingmap-empty-string="false".Ifthisisspecified,thedestfieldmappingisbypassedatruntimeandthedestinationvaluesettermethodwillnotbecalledifthesrcvalueisanemptyString.Thiscanbespecifiedatthemappingorclasslevel

ShouldIencapsulatelogicthatcopiesdatabetweenobjects?

Itisouropinionthatyoushould.RegardlessofwhetheryouuseDozertoperformdatamappingbetweenobjects,webelievethisisagooddesignpatternthatpromotesreuse,encapsulatestheunderlyingimplementation,andmakesthecodeunittestableinisolation.These"Assembler"interfacesencapsulatethelogicthatisresponsiblefortakingasrcobjectandmappingthedataintoadestobject.Usingassemblertypeofclassesgivesyoutheflexibilityofbeingabletomodifytheunderlyingmappingimplementationwithoutimpactingclientsorthecontract.OneotherimportantbenefitofusingAssemblersisthatitmakeswritingunittestsspecificforthemappingaloteasierandmorefocused.Ifyoueverneedtodetermineifaparticularbugisduetomappingofobjects,itissimpletowriteanAssemblerunittest

FAQ

78

Page 79: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

thatreproducestheusecase.Ifyouencapsulateyourdatamappinglogic,youcoulduseDozerformostofmappingsandifyouhavearealcornercase,youhavetheflexibilitytohandcodemappingsforanyobjectsorfields.Forexample,youcouldrunyourmappingthroughDozertomap99%ofyourfieldsandthenhaveamanualmappingforsomeoddballfield.ThiswouldhappenallwithintheAssemblerwithouttheclienthavinganyknowledgeoftheunderlyingimplementation.

Itseemstoworkbestiftheseassemblertypeofclassesare"dumb"andareonlyresponsibleforsimplycopyingdatafromthesourceobjectintothedestinationobject.Anycomplexpostprocessingbusinesslogicthatneedstobeperformedonthedestinationobjectcanbedoneatahigherlevelinclasssesthathavemoreresponsibility.

ThefollowingisasimpleexampleofanassemblertypeclassthatusesDozerforitsunderlyingimplementation.

publicclassSomeAssemblerImplimplementsSomeAssembler{

privateMapperdozerMapper;

publicDestObjectassembleDestObject(SrcObjectsrc){returndozerMapper.map(src,DestObject.class);}

}

ShouldIwriteunittestsfordatamappinglogicthatIuseDozertoperform?

Absolutely.Andofcourse,westronglyrecommendwritingtheunittest(s)first.Evenifyoudon’tuseDozertoperformthedatamappingbetweentwoobjects,thislogicstillneedsisolatedunittests.Datamappinglogic(especiallyhandcoded)iserrorproneandhavingaunittestisinvaluable.Typicallymappingbetweentwoobjectsisrequiredinmultipleareasofasystem,soafocusedunittestofthecentralmappinglogicenablesyoutotestthedatamappinglogicinisolation.Thegreatthingaboutencapsulatingdatamappinglogicandhavingunittestsforthelogicisthatyoucaneasilyswitchouttheunderlyingimplementation.

ForexistingsystemsthatarewantingtomigratetoDozer,werecommendfirstencapsulatinganyexistinghandcodeddatamappingintoanassemblertypeofclassandwriteunittestsforit.ThenswitchoutthehandcodedmappinglogicwithDozerandtheunittestswillbeyoursafetynet.ThemigrationtoDozercanbeincrementalandthisisprobablythebeststrategyforexisitingsystems.

RegardlessofwhetherornotyouuseDozer,unittestingdatamappinglogicistediousandanecessaryevil,butthereisatrickthatmayhelp.Ifyouhaveanassemblerthatsupportsmapping2objectsbi-directionally,inyourunittestyoucandosomethingsimilartothefollowingexample.Thisalsoassumesyouhavedoneagoodjobofimplementingtheequals()methodforyourdataobjects.Theideaisthatifyoumapasourceobjecttoadestinationobjectandthenbackagain,theoriginalsrcobjectshouldequaltheobjectreturnedfromthelastmappingiffieldsweremappedcorrectly.Inthetestcase,youshouldpopulateallthepossiblefieldsintheoriginalsourceobjecttoensurethatallofthefieldsareaccountedforinthemappinglogic.

publicvoidtestAssembleSomeObject()throwsException{SrcObjectsrc=newSrcObject();src.setSomeField("somevalue");src.setSomeOtherField("makesureyousetallthesrcfields"+"withvaluessothatyoufullytestthedatamappings");

DestObjectdest=assembler.assembleDestObject(src);SrcObjectmappedSrc=assermbler.assembleSrcObject(dest);

assertEquals("fieldsnotmappedcorrectly",src,mappedSrc);}

FAQ

79

Page 80: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Itisalsogoodpracticetoverifythatyourassemblerhandlesnullvaluesproperly.Inthefollowingtestcasenoneofthesourcefieldsarepopulated.Iftheassemblerdoesn’tproperlyhandlenullvalues,anexceptionwillbethrownwhentheassemblerisinvoked.

publicvoidtestAssembleSomeObject_NullValues()throwsException{SrcObjectsrc=newSrcObject();

DestObjectdest=assembler.assembleDestObject(src);SrcObjectmappedSrc=assermbler.assembleSrcObject(dest);

assertEquals("fieldsnotmappedcorrectly",src,mappedSrc);}

ShouldtheDozermapperbeconfiguredasaSingleton?

Yes.Mapperinstancesshouldbereusedasmuchaspossible.ForeveryinstanceoftheMapper,themappingfilesareloadedandparsed.YoushouldconfiguretheMapperonceforyourconfigurationandreusethisinstancethroughoutyourapplication.TheMapperimplementationsarethreadsafe.

Isitbettertohave1largexmlmappingfileortohavemultiplesmallermappingfiles?

Werecommendcomponentizingyourmappingfilesinsteadofhaving1largemappingfile.

WhatarethebestwaystodebugDozer?

Youcanspecifythe-Ddozer.debugsystempropertytoviewtheonetimeinitializationinformation.Youwillseeoutputsimilartothefollowing….

dozer:TryingtofindDozerconfigurationfile:dozer.propertiesdozer:UsingURL[file:/local/subversion_projects/dozer/trunk/target/test-classes/dozer.properties]forDozerglobalpropertyconfigurationdozer:ReadingDozerpropertiesfromURL[file:/local/subversion_projects/dozer/trunk/target/test-classes/dozer.properties]dozer:FinishedconfiguringDozerglobalpropertiesdozer:InitializingDozer.Version:${project.version},ThreadName:maindozer:Initializinganewinstanceofthedozerbeanmapper.dozer:Usingthefollowingxmlfilestoloadcustommappingsforthebeanmapperinstance:[fieldAttributeMapping.xml]dozer:Tryingtofindxmlmappingfile:fieldAttributeMapping.xmldozer:UsingURL[file:/local/subversion_projects/dozer/trunk/target/test-classes/fieldAttributeMapping.xml]toloadcustomxmlmappingsdozer:SuccessfullyloadedcustomxmlmappingsfromURL:[file:/local/subversion_projects/dozer/trunk/target/test-classes/fieldAttributeMapping.xml]

Todebugindividualfieldmappingsbetweenclasses,setthelogginglevel"com.github.dozermapper.core.MappingProcessor=DEBUG".Forexample,ifyouareusinglog4jyouwouldaddthefollowingentrytoyourlog4jconfigurationfile"log4j.category.com.github.dozermapper.core.MappingProcessor=DEBUG".ThiswillshowyoueveryfieldmappingthatDozerperformsalongwiththeactualsourceanddestinationvalues.Youwillseeoutputsimilartothefollowing….

MAPPED:SimpleObj.field1-->SimpleObjPrime.field1VALUES:one-->oneMAPID:someMapIdMAPPED:SimpleObj.field2-->SimpleObjPrime.field2VALUES:2-->2MAPID:someMapIdMAPPED:SimpleObj.field3-->SimpleObjPrime.field3VALUES:3-->3MAPID:someMapIdMAPPED:SimpleObj.field4-->SimpleObjPrime.field4VALUES:44.44-->44.44MAPID:someMapIdMAPPED:SimpleObj.field6-->SimpleObjPrime.field6VALUES:

FAQ

80

Page 81: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

66-->66MAPID:someMapId

Whatisthebestwaytosetuptheglobalconfiguration?

Werecommendhavingaseparatemappingxmlfileforglobalconfiguration.Youcouldnameitsomethingsimilartodozer-global-configuration.xml.Sampleglobalconfigurationfile……

<?xmlversion="1.0"encoding="UTF-8"?><mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttp://dozermapper.github.io/schema/bean-mapping.xsd"><configuration><stop-on-errors>true</stop-on-errors><date-format>MM/dd/yyyyHH:mm</date-format><wildcard>false</wildcard><custom-converters><convertertype="com.github.dozermapper.core.converters.TestCustomConverter"><class-a>com.github.dozermapper.core.vo.CustomDoubleObject</class-a><class-b>java.lang.Double</class-b></converter></custom-converters></configuration></mappings>

Whatisthebestwaytosubmitabug,featurerequest,orpatch?

Wevalueyoursuggestionsandappreciateeveryonethattakesthetimetosubmitasupportrequest.PleasesubmitallrequestsviaDozer’sGitHubprojectpage

FAQ

81

Page 82: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

ExamplesTherearesomesamplemappingfilesunder\{dozer.home}/src/test/resources.ThesemappingfilesareusedbytheDozerunittests.

Examples

82

Page 83: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Migrationfromv5.5.1tov6.0.0Seeforreleasenotes.

1.JDK<1.8supportdropped

DozerisbuiltagainstJavaJDK1.8ONLY.

2.MavenGAV(GroupID,ArtifactandVersion)haschanged:

From:

<dependency><groupId>net.sf.dozer</groupId><artifactId>dozer</artifactId><version>5.5.1</version></dependency>

To:

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>6.0.0</version></dependency>

3.dozer-osgidropped

Younolongerneedtousethebelow,ifyouarerunninginanOSGienvironment:

<dependency><groupId>net.sf.dozer</groupId><artifactId>dozer-osgi</artifactId><version>5.5.1</version></dependency>

Justsimplyusethedozer-core:

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>6.0.0</version></dependency>

v5tov6

83

Page 84: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Migrationfromv6.0.0tov6.1.0Seeforreleasenotes.

1.Mapping.xmlXSDchanged:

From:

<mappingsxmlns="http://dozer.sourceforge.net"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozer.sourceforge.nethttp://dozer.sourceforge.net/schema/beanmapping.xsd">

To:

<mappingsxmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mappinghttps://dozermapper.github.io/schema/bean-mapping.xsd">

2.Dozer-SpringXSDchanged.

From:

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dozer="http://dozer.sourceforge.net/schema/dozer-spring"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://dozer.sourceforge.net/schema/dozer-springhttp://dozer.sourceforge.net/schema/dozer-spring.xsd">

To:

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dozer="http://dozermapper.github.io/schema/dozer-spring"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://dozermapper.github.io/schema/dozer-springhttps://dozermapper.github.io/schema/dozer-spring.xsd">

3.DozerBeanMapperusageisdeprecated

DirectinstantiationofDozerBeanMapperaswellasitsusageisdeprecated.Thisclasswillbehiddeninversion6.2.PleaseuseMapperwheneveryouneedtomap,andDozerBeanMapperBuildertoconfigurethemapper.

Deprecated:

DozerBeanMappermapper=newDozerBeanMapper();mapper.addMapping(myMappingBuilder);mapper.setMappingFiles(myFiles);

mapper.map(a,b);

Recommended:

v6.0.0tov6.1.0

84

Page 85: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Mappermapper=DozerBeanMapperBuilder.create().withMappingBuilder(myMappingBuilder).withMappingFiles(myFiles).build();

mapper.map(a,b);

4.DozerBeanMapperSingletonWrapperisdeprecated

DozerBeanMapperSingletonWrapperisdeprecatedandplannedforremovalinversion6.2.

DozerprojectdoesnotadvisetouseJVMsingletons.PleaseuseyourDIcontainertomanagesingleinstanceoftheMapperifrequired.ThefollowingcodecanbeusedtocreateaMapperwithdefaultconfiguration:

Mappermapper=DozerBeanMapperBuilder.buildDefault();

5.InternalAPIischanged

DozerismovingawayfromhavingJVM-globalstate.ThismeansthatsomeinternalAPIlikeBeanContainerisnotavailableanymoreviasingletonreferences,i.e.BeanContainer.getInstance()doesnotexist.Ifyouwereusingthisoranyothercodethatisreworked,pleaseletusknow.MostlikelyyoudevelopedDozerModule.Wewouldliketoknowmoreaboutreal-worldusecasestobuildconvenientpublicAPIformodulesdevelopers.

6.org.dozer.BeanFactoryinterfacechanges

Oldsignatureoforg.dozer.BeanFactoryisdeprecatedandwillberemovedinversion6.2.Pleaseusenewmethodofthisinterfacewhencreatingcustombeanfactories.

Deprecated:

ObjectcreateBean(Objectsource,Class<?>sourceClass,StringtargetBeanId)

Recommended:

ObjectcreateBean(Objectsource,Class<?>sourceClass,StringtargetBeanId,BeanContainerbeanContainer)

7.Deprecatedstatsandjmx

Deprecated:

org.dozer.statsorg.dozer.jmx

8.Updateddozer-protopackagename

From:

org.dozer

To:

com.github.dozermapper.protobuf

v6.0.0tov6.1.0

85

Page 86: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

9.Updateddozer-springpackagename

From:

org.dozer.spring

To:

com.github.dozermapper.spring

v6.0.0tov6.1.0

86

Page 87: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Migrationfromv6.1.0tov6.2.0Seeforreleasenotes.

1.JMX/Statshasbeenremoved

Asper6.1.0migrationdocs,JMXandStatsweredeprecated.Theyhavenowbeenfullyremoved.

2.dozer.propertieskeyschanged

From:

dozer.cache.converter.by.dest.type.maxsizedozer.cache.super.type.maxsizeorg.dozer.util.DozerClassLoaderorg.dozer.util.DozerProxyResolver

To:

dozer.cache.converter-by-dest-type-maxsizedozer.cache.super-type-maxsizedozer.beans.class-loader-beandozer.beans.proxy-resolver-bean

3.SupportforYAML,SystemPropertiesandEnvironmentvariables

Asaswellasdozer.properties,wealsosupportseveralnewimplementations,suchasYAML,see:-https://github.com/DozerMapper/dozer/tree/6.2.0/core/src/main/java/org/dozer/config/resolvers-https://github.com/DozerMapper/dozer/tree/6.2.0/core/src/main/java/org/dozer/config/processors

4.dozer.el.enabledisdeprecated

Thepropertyfor'dozer.el.enabled'hasbeendeprecated.Instead,youshoulduse:

DefaultELEngineelEngine=newDefaultELEngine();Mappermapper=DozerBeanMapperBuilder.create().withMappingFiles(mappingFiles).withElementReader(newExpressionElementReader(elEngine)).withELEngine(elEngine).build();

5.Springmavenartifactnamehaschanged

From:

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring</artifactId><version>6.1.0</version></dependency>

To:

v6.1.0tov6.2.0

87

Page 88: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring4</artifactId><version>6.2.0</version></dependency>

6.Springmavenartifactnamehaschanged

From:

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-proto</artifactId><version>6.1.0</version></dependency>

To:

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-proto3</artifactId><version>6.2.0</version></dependency>

7.Extendedspringbootsupport

dozer-spring-boot-starteranddozer-spring-boot-autoconfigureartifactsaddedtosupportspringbootautoconfigurationfeatures.

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring-boot-starter</artifactId><version>6.2.0</version></dependency>

8.dozer.xml.use-jaxb-mapping-enginetousenewJAXB

ThecurrentDozerXMLtoObjectsimplementationusesorg.w3c.dom.Documenttoparsethemodel.Goingforward,theintentionistouseaJAXBmodel.Thisfeatureisnotenabledbydefault,butcanbevia:

dozer.xml.use-jaxb-mapping-engine=true

v6.1.0tov6.2.0

88

Page 89: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Migrationfromv6.2.0tov6.3.0Seeforreleasenotes.

1.Karaf2supportdropped

Askaraf2isnowdeprecatedupstream,andisnotsupportedwithJava9,supportisdropped.

2.ApacheXMLBeanssupportdropped

Asxmlbeansisnowdeprecatedupstream,andisnotsupportedwithJava9,supportisdropped.

3.UberJARnowprovided

MavenGAV

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-core</artifactId><version>6.3.0</version><classifier>jar-with-dependencies</classifier></dependency>

4.dozer.xml.use-jaxb-mapping-engineenabledbydefault

JAXBisusedbydefault,ifthiscausesissues,itcanbedisabledvia:

-Ddozer.xml.use-jaxb-mapping-engine=false

Andthefollowingisdeprecated:

com.github.dozermapper.core.loader.xml

Infavourof:

com.github.dozermapper.core.builder.xml

5.Updateddozer-corepackagename

From:

org.dozer

To:

com.github.dozermapper.core

6.UpdatedDozerEventListenerpackage/classname

From:

v6.2.0tov6.3.0

89

Page 90: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

org.dozer.DozerEventListener

To:

com.github.dozermapper.core.events.EventListener

v6.2.0tov6.3.0

90

Page 91: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

PrerequisitesThePlugincurrentlydependson

WTP3.0.2orlatest

Compatibility

PluginissupportedandbeentestedonthefollowingIDEs

Eclipse3.6

RADRSA8.0.1

Installation

TheDozerPlugin-featurecanbeinstalledandupdatedusingtheEclipseUpdateManager.

AddanewUpdate-URL:

http://dozer.sourceforge.net/eclipse-plugin

Selectallrequireddependenciesandinstalltheplugin.

Alternativelyyoucandownloadthepackageatsourceforgeandunzipitinyoureclipseinstallationfolder.YoumighthavetoenablethePluginafterstartingEclipse.ThiscanbedoneatHelp>SoftwareUpdates>ManageConfiguration.

Afterinstallationisdoneyoushouldseealittlereddozer-icononallyourmapping-xmlfiles.

Installation

91

Page 92: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

CreatenewMappingfilesThepluginprovidesasimplewizardforcreatingnewmapping-xmlfiles.Anewmapping-xmlfilecanbecreatedusingFile>New>Other>DozerMappingFramework>DozerMappingFile.Selectthecorrectdozerversion(4,DTDor5,XSD)inthewizardandcreatethefile.

ConfiguretheMapping

viaXML

viatheEditor

Usage

92

Page 93: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

OpenmappingfileWhenopeningaDozer-mapping-filetheDozer-editorappears.IfyouwanttoedittherawXMLyoucanswitchtothe"source"view.

ContentAssist

Alltheclass-a/class-b,field,get-method,set-method,etc-nodesor-attributesautomaticlyshowcontent-assistpopupswhenpressingctrl+spaceortheconfiguredWTP-XMLcontentassistcharacters.Thesecanbechangedinthepreferences.

viaXML

93

Page 94: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Alltheclass-a/class-b,field,get-method,set-method,etc-nodesor-attributesautomaticlyshowcontent-assistpopupswhenpressingctrl+spaceortheconfiguredWTP-XMLcontentassistcharacters.Thesecanbechangedinthepreferences.

viaXML

94

Page 95: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

Validation

TheDozerPluginvalidatestheMappingtofindoutifthemappedclassdoexistandifthemappedfieldsareaccessible.

viaXML

95

Page 96: Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using Apache Maven, simply copy-paste this dependency to your project

SettingglobaldozerconfigurationAllglobalconfigurationvaluescanbesetinthe"GlobalConfiguration"Tab.

Configuringmappings

Everyclassmappingislistedinthe"Mapping"Tab.MappingsofclassesandfieldscanbeaddedbyPopupmenuortheaction-buttonsatthetop.Ontherightsidethemappingscanbeconfigured.EveryAttributeorElementintheXMLfileisshownforediting.

viaEditor

96