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

Transcript of Table of Contents - GitHub Pages · Getting Started Downloading the Distribution If you are using...

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