Dozer User Guide
Dozer User Guide
of Contents
Introduction 1.1
Usage 1.3.1
Configuration 1.5
Advanced Configuration 1.5.1
Global Configuration 1.5.2
1
Enums 3.1
String to Date 3.2
Collections and Arrays 3.3
Extra
Logging 5.1
Event Listening 5.2
Statistics 5.3
JMX Integration 5.4
3rd Party
Spring Integration 6.1
JAXB and XMLBeans 6.2
Other
2
FAQ 7.1
Examples 7.2
Migration
v5 to v6 8.1
Schema
schema/bean-mapping.xsd[Dozer Mapping XSD] 9.1
dozer-user-guide.pdf[User’s Guide PDF] 9.2
Eclipse Plugin
Installation 10.1
Usage 10.2
via XML 10.2.1
3
Introduction
Dozer
What is Dozer?
Dozer is a Java Bean to Java Bean mapper that recursively copies data from one
object to another. Typically, these Java Beans will be of different complex types.
4
Why Map?
Why Map?
A mapping framework is useful in a layered architecture where you are creating
layers of abstraction by encapsulating changes to particular data objects vs.
propagating these objects to other layers (i.e. external service data objects, domain
objects, data transfer objects, internal service data objects). A mapping framework is
ideal for using within Mapper type classes that are responsible for mapping data
from one data object to another.
For distributed systems, a side effect is the passing of domain objects between
different systems. Typically, you won’t want internal domain objects exposed
externally and won’t allow for external domain objects to bleed into your system.
Mapping between data objects has been traditionally addressed by hand coding
value object assemblers (or converters) that copy data between the objects. Most
programmers will develop some sort of custom mapping framework and spend
countless hours and thousands of lines of code mapping to and from their different
data object.
Serialization Requirements
Framework Integration
5
Why Map?
In some cases it is efficient to guard your code base from frequently changing object
hierarchy, which you do not control directly. In this case Dozer serves as a bridge
between application and external objects. As mapping is performed in reflective
manner not all changes break your API. For example if object changes from Number
to String the code will keep working as this is resolved automatically.
Some frameworks impose Serialization constraints, which does not allow sending
any Java objects through the wire. One of the popular examples is Google Web
Toolkit (GWT) framework, which restricts developer to sending only objects compiled
to JavaScript and marked as Serializable. Dozer helps to convert Rich Domain
Model to Presentation Model, which satisfies GWT serialization requirements.
Dozer integrates nicely with frameworks such as Apache XmlBeans and JAXB
implementations. With help of provided factory classes, conversion between domain
model and Xml objects is defined in the same way as plain object to object
mappings.
6
Getting Started
Getting Started
Downloading the Distribution
If you are using Apache Maven, simply copy-paste this dependency to your project.
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>6.1.0</version>
</dependency>
1st Mapping
For your first mapping, lets assume that the two data objects share all common
attribute names.
After performing the Dozer mapping, the result will be a new instance of the
destination object that contains values for all fields that have the same field name as
the source object. If any of the mapped attributes are of different data types, the
Dozer mapping engine will automatically perform data type conversion. At this point
you have completed your first Dozer mapping. Later sections will go over how to
specify custom mappings via custom xml files.
7
Getting Started
Dozer automatically performs any type conversion when copying the source field
data to the destination field. The Dozer mapping engine is bi-directional, so if you
wanted to map the destination object to the source object, you do not need to add
another class mapping to the xml file.
IMPORTANT: Fields that are of the same name do not need to be specified in the
mapping xml file. Dozer automatically maps all fields with the same property name
from the source object into the destination object.
i.e.:
<mapping>
<class-a>yourpackage.yourSourceClassName</class-a>
<class-b>yourpackage.yourDestinationClassName</class-b>
<field>
<a>yourSourceFieldName</a>
<b>yourDestinationFieldName</b>
</field>
</mapping>
The complete Dozer mapping xml file would look like the following. The Custom
Mappings section contains more information on mapping options that are available to
you for more complex use cases.
8
Getting Started
</mappings>
9
Usage
Usage
Dozer Bean Mapper
Before we go over setting up custom xml bean mappings, let us look at a simple
example of using Dozer. The Dozer mapping implementation has a method called
map which takes a source object and either a destination object or destination object
class type. After mapping the two objects it then returns the destination object with
all of its mapped fields.
Or…
Implicit mode is activated by default and tries to resolve mappings for you. It uses
simple assumptions that if two objects are passed for mapping then bean properties
with the same names should be mapped. If there are additional mappings needed,
which can not be derived by the naming you should add those either via XML,
annotations or API.
Explicit mode assumes that no mappings should be performed or "guessed" until you
have specified those specifically. The amount of coding is higher in explicit mode,
but sometimes you would like to have full control on what is going on during the
mappings process and this approach is also used in many of the productive
applications. Implicit/Explicit mapping switch is called "wildcard" in Dozer.
10
Usage
The Dozer mapping xml file(s) define any custom mappings that can’t be
automatically performed by the Dozer mapping engine. Any custom Dozer mapping
files need to be injected into the Mapper implementation via
DozerBeanMapperBuilder#withMappingFiles(..) method.
Preferably, you will be using an IOC framework such as Spring for these Dozer
injection requirements. Alternatively, the injection of mapping files can be done
programmatically. Below is a programmatic approach to creating a bean mapper.
Note that this is NOT the recommended way to retrieve the bean mapper. Each
new instance needs to be initialized and this consumes time as well as resources. If
you are using the mapper this way just wrap it using the singleton pattern.
Spring Integration
The following is an example how the Mapper bean would be configured via Spring.
11
Mappings via XML
Dozer automatically performs any type conversion when copying the source field
data to the destination field. The Dozer mapping engine is bi-directional, so if you
wanted to map the destination object to the source object, you do not need to add
another class mapping to the xml file.
A mappings element has multiple mapping elements, each with class mapping
declarations and field level mappings. The wildcard attribute is set to true by default.
This means that it will automatically try to map every property in the two objects.
12
Mappings via XML
When the attribute is set to false it will only map explicitly defined fields.
IMPORTANT: Properties that are of the same name do not need to be specified in
the mapping xml file. Dozer automatically maps all fields with the same property
name from the source object into the destination object.
Alternatively, you can load files from outside the classpath by prepending "file:" to
the resource name. Ex) "file:c:\somedozermapping.xml"
13
via Annotations
Annotation Mappings
Why Annotations?
One of the downsides of using Dozer for the long time was Xml. Since Dozer started
during Xml-hype years more than five years ago that was pretty obvious choice back
then. After that Java 5 brought us annotations and new industry accepted style of
configuring behaviour are Domain-Specific Languages. DSL-like support is provided
in form of mapping API, but since version 5.3.2 Dozer starts providing annotations
support as well.
The obvious reasons to use annotations is to avoid duplicating field and method
names in your mapping code. The annotation can be put onto the mapped property
itself thus reducing the amount of code. However there are cases when annotations
should be avoided or even impossible to use. Some of them are the following:
You are mapping classes, which are not under your control, but provided in
libraries;
In the first case you could be mapping JAXB generated entities or third-party DTOs
and have no possibility to put annotations. In the second case there is a choice of
putting lots of multi-line annotations or isolating the mapping code with certain
duplication of entity names. Overannotated beans could be problematic to read and
understand.
Usage
WARNING: Annotation support in Dozer is experimental and does not cover
complex use cases yet. However it may be useful to implement that simplest
mappings you have had to do in Xml or API before.
The idea is very simple. You put @Mapping annotation either on getter of field
directly. If Dozer finds that it adds a bi-directional mapping. It means that putting
annotation once will create mappings for both conversion types. Type conversions
14
via Annotations
@Mapping("binaryData")
private String data;
@Mapping("pk")
public Long getId() {
return this.id;
}
Mapping the given beans with Dozer will result in all three fields being mapped.
Property "name" will be mapped by naming convention. Property "id" will be
transformed to "pk". Field "data" will be moved to "binaryData". Do not worry about
private modifier; it will be handled automatically.
15
via Annotations
Currently Dozer offers only one annotation, but the next ones will be added in
following releases. As for now you can mix and match all flavours of mapping types
to achieve the desired effect: Xml, API and Annotations.
16
via API
API Mappings
XML Mapping Flaws
XML-based approach is stable and is used in many production projects. However, it
imposes several limitations.
First, and most important, is that it can not be dynamically generated. All XML
mappings should be present on Dozer start-up and can not be modified
afterwards. There are tricky ways, when you can generate and put mappings to
the file system by your own templating engine, but this approach is not
supported by Dozer itself. By generating custom mappings you are able to
automate repetitive chunks of low-level Dozer language.
Second problem is that you are forced to duplicate all of your Bean class names
in Xml mappings. This leads to lots of typing and copy-paste programming. This
can be partly compensated by use of Expression Language inside Xml, but it is
not solving all of the problems.
Refactoring support is limited as IDE should keep track of class names in Xml
files and change them when you rename or move the referenced class. Auto-
completion support is also not available in all IDEs.
API Mappings
API mappings are intended to solve all of the mentioned problems. To preserve
backwards compatibility API mappings can be combined with existing Xml mappings.
In fact some parts of the configuration (e.g. global configuration block) are only
possible to express in Xml format.
To get a feeling of what are these mappings take a look at the following code
example.
import org.dozer.classmap.RelationshipType;
import org.dozer.loader.api.BeanMappingBuilder;
import org.dozer.loader.api.FieldsMappingOptions;
import org.dozer.loader.api.TypeMappingOptions;
17
via API
18
via API
19
Configuration
Configuration
Dozer configuration properties can be customized via an optional Dozer properties
file. By default, Dozer will look for a file named dozer.properties to load configuration
properties. If a properties file is not found or specified, default values will be used.
Dozer is distributed with an example dozer.properties file in /config that shows the
various options. Just put the example file in your classpath and customize it.
Specifies whether
Dozer collects
runtime mapping
statistics. Note that
statistics gathering
imposes certain
dozer.statistics.enabled true
performance
overhead. It is not
recommended to
enable this option in
production settings
under heavy load.
Specifies whether
Dozer will auto
register it’s JMX
dozer.autoregister.jmx.beans true
beans with the
PlatformMDBServer
on startup.
Specifies whether
during Xml
dozer.el.enabled mappings parsing true
Dozer will recognize
EL expressions.
20
Configuration
Specifies
implementation of
org.dozer.util.DozerProxyResolver Valid class name
DozerProxyResolver
to be used
Specifies
implementation of
org.dozer.util.DozerClassLoader Valid class name
DozerClassLoader
to be used
21
Advanced Configuration
Dozer supports the ability to have multiple mapping files. Each of these mapping files
can have their own configuration block. A mapping will inherit its configuration from
the mapping file that it is stored in. Implicit mappings will inherit the default
values for configuration.
The following is the sample configuration block from the example mappings file:
<configuration>
<date-format>MM/dd/yyyy HH:mm</date-format>
<stop-on-errors>true</stop-on-errors>
<wildcard>true</wildcard>
<custom-converters>
<!-- these are always bi-directional -->
<converter type="org.dozer.converters.TestCustomConverter">
<class-a>org.dozer.vo.TestCustomConverterObject</class-a>
<class-b>another.type.to.Associate</class-b>
</converter>
</custom-converters>
</configuration>
Overriding Wildcards
Each individual mapping section can set its own wildcard policy even if there is a
global wildcard policy defined using the configuration block. For example, the
following mapping does not allow wildcards:
<mapping wildcard="false">
<class-a>org.dozer.vo.SpringBean</class-a>
<class-b>org.dozer.vo.SpringBeanPrime</class-b>
<field>
<a>anAttributeToMap</a>
<b>anAttributeToMapPrime</b>
</field>
</mapping>
22
Advanced Configuration
<mapping map-null="false">
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b>org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
23
Advanced Configuration
</field>
</mapping>
OR…
<mapping>
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b map-null="false">org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
<mapping map-empty-string="false">
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b>org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
OR…
<mapping>
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b map-empty-string="false">org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
24
Advanced Configuration
<mapping type="one-way">
<class-a>org.dozer.vo.TestObjectFoo</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime</class-b>
<field>
<a>oneFoo</a>
<b>oneFooPrime</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.TestObjectFoo2</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime2</class-b>
<field type="one-way">
<a>oneFoo2</a>
<b>oneFooPrime2</b>
</field>
<field type="one-way">
<a>oneFoo3.prime</a>
<b>oneFooPrime3</b>
</field>
</mapping>
25
Global Configuration
Global Configuration
The configuration block is used to set the global default settings. Also, any Custom
Converters are defined in this section. The configuration block is entirely "optional".
Dozer supports the ability to have multiple mapping files, but only one global
configuration across the multiple mapping files. We recommend having a separate
mapping xml file for specifying the single global configuration. Implicit mappings
will inherit the default values for configuration.
<configuration>
<date-format>MM/dd/yyyy HH:mm</date-format>
<stop-on-errors>true</stop-on-errors>
<wildcard>true</wildcard>
<trim-strings>false</trim-strings>
<custom-converters>
<!-- these are always bi-directional -->
<converter type="org.dozer.converters.TestCustomConverter">
<class-a>org.dozer.vo.TestCustomConverterObject</class-a>
<class-b>another.type.to.Associate</class-b>
</converter>
</custom-converters>
</configuration>
Overriding Wildcards
Each individual mapping section can set its own wildcard policy even if there is a
global wildcard policy defined using the configuration block. For example, the
following mapping does not allow wildcards:
<mapping wildcard="false">
<class-a>org.dozer.vo.SpringBean</class-a>
<class-b>org.dozer.vo.SpringBeanPrime</class-b>
<field>
<a>anAttributeToMap</a>
<b>anAttributeToMapPrime</b>
</field>
</mapping>
26
Global Configuration
27
Global Configuration
28
Mapping Classes
Mapping Classes
An example of mapping two classes is defined below. Note: Explicit xml mapping for
2 classes is not required if all the field mapping between src and dest object can be
performed by matching on attribute name. Custom xml class mapping is only
required when you need to specify any custom field mappings.
<mappings>
<mapping>
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<!-- Any custom field mapping xml would go here -->
</mapping>
</mappings>
These mappings are bi-directional so you would never need to define an XML map
for TestObjectPrime to TestObject. If these two classes had references to complex
types that needed type transformation, you would also define them as mappings.
Dozer recursively goes through an object and maps everything in it. Data type
conversion is performed automatically. Dozer also supports no attribute mappings at
all. If supplied two classes that are not mapped, it simply tries to map properties that
are the same name.
29
Basic Property Mapping
Properties that are of the same name do not need to be specified in the
mapping xml file.
<field>
<a>one</a>
<b>onePrime</b>
</field>
Primitive to Primitive
String to Primitive
30
Basic Property Mapping
String to Map
Collection to Collection
Collection to Array
Enum to Enum
31
Inheritance Mapping
Inheritance Mapping
Reducing Mapping XML when using base class
attributes
Properties that are of the same name do not need to be specified in the
mapping xml file unless hints are needed.
If you are mapping subclasses that also have have base class attributes requiring
mapping XML, you might be inclined to reproduce base class field maps in each
subclass mapping element, like the following example:
<mapping>
<class-a>org.dozer.vo.SubClass</class-a>
<class-b>org.dozer.vo.SubClassPrime</class-b>
<field>
<!-- this is the same for all sub classes -->
<a>superAttribute</a>
<b>superAttr</b>
</field>
<field>
<a>attribute2</a>
<b>attributePrime2</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SubClass2</class-a>
<class-b>org.dozer.vo.SubClassPrime2</class-b>
<field>
<!-- this is the same for all sub classes -->
<a>superAttribute</a>
<b>superAttr</b>
</field>
<field>
<a>attribute2</a>
<b>attributePrime2</b>
</field>
</mapping>
In the previous mapping, some of the fields were from a common base class, but you
had to reproduce them into each mapping of the sub classes.
32
Inheritance Mapping
However, a better way to do it would be to map the base class individually. This can
be done for each base class (in the case of a larger heirarchy). Assuming the base
class name, below is the refactored mapping xml:
<mapping>
<class-a>org.dozer.vo.SuperClass</class-a>
<class-b>org.dozer.vo.SuperClassPrime</class-b>
<field>
<a>superAttribute</a>
<b>superAttr</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SubClass</class-a>
<class-b>org.dozer.vo.SubClassPrime</class-b>
<field>
<a>attribute</a>
<b>attributePrime</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SubClass2</class-a>
<class-b>org.dozer.vo.SubClassPrime2</class-b>
<field>
<a>attribute2</a>
<b>attributePrime2</b>
</field>
</mapping>
The following images explain some of the different scenarios dozer handles. Each
diagram shows two mapped class hierarchies and existing relations, which Dozer
recognizes and maps.
33
Inheritance Mapping
Scenario 1 shows that if you map SubClass to ClassPrime all attributes from
SuperClass → ClassPrime will be mapped as well.
Scenario 2 shows that Dozer has no limitations on the inheritance depth it analyzes
to find parent mappings.
34
Inheritance Mapping
Scenario 3 shows that it is possible to map two collections with different subctypes of
the same parent type. This is done by providing hints to the collection mapping,
describing all potential subclasses.
<field>
<a>aList</a>
<b>bList</b>
<a-hint>B1,B2</a-hint>
<b-hint>BPrime1,BPrime2</b-hint>
</field>
35
Context Based Mapping
<mapping map-id="caseA">
<class-a>org.dozer.vo.context.ContextMapping</class-a>
<class-b>org.dozer.vo.context.ContextMappingPrime</class-b>
<field-exclude>
<a>loanNo</a>
<b>loanNo</b>
</field-exclude>
<field map-id="caseC">
<a>contextList</a>
<b>contextList</b>
<b-hint>org.dozer.vo.context.ContextMappingNestedPrime
</b-hint>
</field>
</mapping>
<mapping map-id="caseB">
<class-a>org.dozer.vo.context.ContextMapping</class-a>
<class-b>org.dozer.vo.context.ContextMappingPrime</class-b>
</mapping>
<mapping map-id="caseC">
<class-a>org.dozer.vo.context.ContextMappingNested</class-a>
<class-b>org.dozer.vo.context.ContextMappingNestedPrime
</class-b>
<field-exclude>
<a>loanNo</a>
<b>loanNo</b>
</field-exclude>
</mapping>
<mapping map-id="caseD">
<class-a>org.dozer.vo.context.ContextMappingNested</class-a>
<class-b>org.dozer.vo.context.ContextMappingNestedPrime
</class-b>
</mapping>
To use a particular context when invoking the Mapper, you simply specify the map-id
in your mapping call.
36
Context Based Mapping
37
One-Way Mapping
One-Way Mapping
You can set how a mapping definition behaves as far as direction goes. If you only
want to map two classes to go one-way you can set this at the mapping level. The
default is bi-directional. This can be set at the mapping level OR the field level. When
one-way is specified, "a" is always the src object and "b" is always the destination
object.
<mapping type="one-way">
<class-a>org.dozer.vo.TestObjectFoo</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime</class-b>
<field>
<a>oneFoo</a>
<b>oneFooPrime</b>
</field>
</mapping>
In the following example the one-way fields are only mapped when "a" object is
mapped to "b" object. If "b" is mapped to "a", then the field is not mapped.
<mapping>
<class-a>org.dozer.vo.TestObjectFoo2</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime2</class-b>
<field type="one-way">
<a>oneFoo2</a>
<b>oneFooPrime2</b>
</field>
<field type="one-way">
<a>oneFoo3.prime</a>
<b>oneFooPrime3</b>
</field>
</mapping>
38
One-Way Mapping
<field-exclude type="one-way">
<a>fieldToExclude</a>
<b>fieldToExclude</b>
</field-exclude>
39
Copying By Object Reference
<field copy-by-reference="true">
<a>copyByReference</a>
<b>copyByReferencePrime</b>
</field>
This is also supported at the class level. Just define the classes you want to be
copied by reference in the configuration block.
<configuration>
<copy-by-references>
<copy-by-reference>
org.dozer.vo.NoExtendBaseObjectGlobalCopyByReference
</copy-by-reference>
</copy-by-references>
</configuration>
On the class level wildcard expressions are allowed. Copy by reference is applied
via mask, which can inlcude multiple wildcard (*) characters.
<configuration>
<copy-by-references>
<copy-by-reference>
org.dozer.vo.*
</copy-by-reference>
<copy-by-reference>
org.dozer.*.vo.*DTO
</copy-by-reference>
</copy-by-references>
</configuration>
40
Copying By Object Reference
<mapping>
<classa>org.dozer.vo.self.SimpleAccount</classa>
<classb>org.dozer.vo.self.Account</classb>
<field>
<a>this</a>
<b>address</b>
</field>
</mapping>
<mapping>
<classa>org.dozer.vo.self.SimpleAccount</classa>
<classb>org.dozer.vo.self.Address</classb>
<field>
<a>streetName</a>
<b>street</b>
</field>
</mapping>
41
Deep Property Mapping
<mapping>
<class-a>org.dozer.vo.deep.SrcDeepObj</class-a>
<class-b>org.dozer.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.List to java.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>org.dozer.vo.TheFirstSubClass</a-hint>
<b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint>
</field>
<field copy-by-reference="true">
<a>srcNestedObj.hintList3</a>
<b>hintList3</b>
</field>
</mapping>
42
Deep Property Mapping
<field>
<a>offSpringName</a>
<b>pets[1].offSpring[2].petName</b>
</field>
Destination Hints are NOT required if the indexed collection is an Array or if you are
using jdk 1.5 Generics. Dozer is able to automatically determine the property type for
these use cases. But you will need to provide hints if the data types are not Arrays or
if you are not using Generics. This is required so that Dozer knows what types of
dest objects to create while it traverses the deep field mapping.
<field>
<a>someField</a>
<b>someList[1].someOtherList[0].someOtherField</b>
<b-deep-index-hint>
org.dozer.vo.TestObject, org.dozer.vo.AnotherTestObject
</b-deep-index-hint>
</field>
43
Indexed Property Mapping
<mapping>
<class-a>org.dozer.vo.Individuals</class-a>
<class-b>org.dozer.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>
44
Excluding Fields
Excluding Fields
Dozer supports excluding fields from a mapping using the field-exclude tag. We also
support field excludes going one-way as shown in the example.
<field-exclude>
<a>fieldToExclude</a>
<b>fieldToExclude</b>
</field-exclude>
<field-exclude type="one-way">
<a>fieldToExclude</a>
<b>fieldToExclude</b>
</field-exclude>
<mapping wildcard="false">
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b>org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field1</a>
<b>field1</b>
</field>
</mapping>
This configuration would cause only the fields field1 in both classes to be mapped,
even if both classes share a property with the same name called`field2`.
45
Excluding Fields
example:
<mapping map-null="false">
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b>org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
OR…
<mapping>
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b map-null="false">org.dozer.vo.AnotherTestObjectPrime
</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
<mapping map-empty-string="false">
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b>org.dozer.vo.AnotherTestObjectPrime</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
OR…
<mapping>
46
Excluding Fields
<class-a>org.dozer.vo.AnotherTestObject</class-a>
<class-b map-empty-string="false">
org.dozer.vo.AnotherTestObjectPrime
</class-b>
<field>
<a>field4</a>
<b>to.one</b>
</field>
</mapping>
47
Assembler Pattern
Mapping Concepts
Assembler Pattern
Dozer can be used as an Assembler . Martin Fowler has a great explanation of why
and when you would use an Assembler . Basically, it is a way to take multiple fine
grain objects and create one coarse grain object used for data transfer. As long as
you have mappings defined for each of your fine grained objects to your coarse grain
object you can call the mapper multiple times to achieve the desired assembler
pattern.
mapper.map(sourceA, ClassB.class);
Let’s say that ClassA, ClassB, and ClassC all map to ClassD. First create these
individual mappings in the mapping file. Next, call the mapper once for each
mapping. Note that this would also work in a bi-directinonal manner.
48
Enums
Enum Mapping
To map an enums value to another enum is shown below.
<field>
<a>status</a>
<b>statusPrime</b>
</field>
enum Status {
PROCESSING, SUCCESS, ERROR
}
enum StatusPrime {
PROCESSING, SUCCESS, ERROR
}
49
Enums
50
String to Date
<field>
<a date-format="MM/dd/yyyy HH:mm:ss:SS">dateString</a>
<b>dateObject</b>
</field>
A default date format can also be specified at the class mapping level. This default
date format will be applied to all field mappings unless it is overridden at the field
level.
A default date format can also be specified at the very top mappings level. This
default date format will be applied to all field mapppings unless it is overridden at a
lower level
<mappings>
<configuration>
<date-format>MM/dd/yyyy HH:mm</date-format>
</configuration>
<mapping wildcard="true">
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>dateString</a>
<b>dateObject</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SomeObject</class-a>
51
String to Date
<class-b>org.dozer.vo.SomeOtherObject</class-b>
<field>
<a>srcField</a>
<b>destField</b>
</field>
</mapping>
</mappings>
52
Collections and Arrays
List to List
List to Array
Array to Array
Set to Set
Set to Array
Set to List
Below is a summary of the mapping logic used when mapping Arrays, Sets, and
Lists. This gives a breakdown of what happens when hints are or are not used.
53
Collections and Arrays
List to List
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
Array to List
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
List to Array
If no dest hint specified: Dest array will contain data types defined by the
array
If hint is speficied: Dest list will contain objects that match dest hint(s) type
(only if Object Array)
Array to Array
If no dest hint specified: Dest array will contain data types defined by the
array
If hint is speficied: Dest list will contain objects that match dest hint(s) type
(only if Object Array)
54
Collections and Arrays
Set to Set
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
Array to Set
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
Set to Array
If no dest hint specified: Dest array will contain data types defined by the
array
If hint is speficied: Dest list will contain objects that match dest hint(s) type
(only if Object Array)
List to Set
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
Set to List
55
Collections and Arrays
If no dest hint specified: Dest list will contain the same data types in the
source
If hint is speficied: Dest list will contain objects that match dest hint(s) type
}
public class UserGroupPrime {
56
Collections and Arrays
Use a hint for data type conversion. Because a hint is specified, the destination List
will contain String elements instead of Integers.
57
Collections and Arrays
<mappings>
<configuration>
<relationship-type>non-cumulative</relationship-type>
</configuration>
</mappings>
<mappings>
<mapping relationship-type="non-cumulative">
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>someList</a>
<b>someList</b>
</field>
</mapping>
</mappings>
<!-- objects will updated if already exist in List, added if they are not present -->
<field relationship-type="non-cumulative">
<a>unequalNamedList</a>
<b>theMappedUnequallyNamedList</b>
</field>
58
Collections and Arrays
Note: if you do not define custom equals() and hashCode() methods non-cumulative
option will not function properly, as Dozer will fail to determine object equality and
will rely on JDK generated object Ids. In default case two instances of a class are
always treated as different and update will not occure.
Removing Orphans
Orphans are elements which exist in a destination collection that did not exist within
the source collection. Dozer will remove orphans by calling the 'remove' method on
actual orphans of the underlying destination collection; it will not clear all. To
determine elements which are orphans dozer uses the contains() method to check if
the results contains orphans. The default setting value is false.
<!-- orphan objects will always be removed from an existing destination List -->
<field remove-orphans="true">
<a>srcList</a>
<b>destList</b>
</field>
59
Map Backed Property Mapping
<mapping>
<class-a>org.dozer.vo.map.MapToMap</class-a>
<class-b>org.dozer.vo.map.MapToMapPrime</class-b>
<field>
<a>standardMapWithHint</a>
<b>standardMapWithHint</b>
<a-hint>org.dozer.vo.TestObject</a-hint>
<b-hint>org.dozer.vo.TestObjectPrime</b-hint>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.map.PropertyToMap</class-a>
<class-b>org.dozer.vo.map.MapToProperty</class-b>
<field>
<a>stringProperty</a>
<b>hashMap</b>
</field>
</mapping>
60
Map Backed Property Mapping
This example shows Field A is a basic String and it is mapped to Field B which is a
HashMap. The key in the HashMap will be "myStringProperty" and the value will be
whatever value is stored in that attribute. Also notice that Field A has a unique
setter() method name.
<mapping>
<class-a>org.dozer.vo.map.PropertyToMap</class-a>
<class-b>org.dozer.vo.map.MapToProperty</class-b>
<field>
<a set-method="addStringProperty2">stringProperty2</a>
<b key="myStringProperty">hashMap</b>
</field>
</mapping>
This example shows Field A is a basic String and it is mapped to Field B which is a
custom map. The key in the custom map will be "myCustomProperty" and the value
will be whatever value is stored in that attribute. Notice that Field B has unique map
getter() and map setter() method names. If you are using a custom map you must
explicitly set the map Get/Set method names. A destination hint can also be provided
if your custom map implements an Interface or is an Abstract class.
<mapping>
<class-a>org.dozer.vo.map.PropertyToMap</class-a>
<class-b>org.dozer.vo.map.MapToProperty</class-b>
<field>
<a>stringProperty3</a>
<b map-get-method="getValue" map-set-method="putValue" key="myCustomProperty">
customMap</b>
</field>
<field>
<a>stringProperty4</a>
<b map-get-method="getValue" map-set-method="putValue" key="myCustomNullProper
ty">nullCustomMap</b>
<b-hint>org.dozer.vo.map.CustomMap</b-hint>
</field>
<field>
<a>stringProperty5</a>
<b map-get-method="getValue" map-set-method="putValue">customMap</b>
</field>
</mapping>
61
Map Backed Property Mapping
The second example shows how to setup a custom map object. The only difference
here is that you need to explicitly define map-set-method and map-get-method
values. These correspond to the java.util.Map get() and put() methods.
<mapping map-id="myTestMapping">
<class-a>org.dozer.vo.map.PropertyToMap</class-a>
<class-b>java.util.Map</class-b>
<field>
<a set-method="addStringProperty2">stringProperty2</a>
<b key="myStringProperty">this</b>
</field>
<field-exclude>
<a>excludeMe</a>
<b>this</b>
</field-exclude>
</mapping>
<mapping map-id="myCustomTestMapping">
<class-a>org.dozer.vo.map.PropertyToMap</class-a>
<class-b map-set-method="putValue" map-get-method="getValue">
org.dozer.vo.map.CustomMap
</class-b>
<field>
<a set-method="addStringProperty2">stringProperty2</a>
<b key="myStringProperty">this</b>
</field>
<field-exclude>
<a>excludeMe</a>
<b>this</b>
</field-exclude>
</mapping>
62
Map Backed Property Mapping
The example below shows how to use these mappings. Notice that the field
mappings reference a map-id. The first field mapping will use the myTestMapping
defined mapping and map accordingly. Same goes with the custom mapping.
<mapping>
<class-a>org.dozer.vo.map.MapTestObject</class-a>
<class-b>org.dozer.vo.map.MapTestObjectPrime</class-b>
<field map-id="myTestMapping">
<a>propertyToMap</a>
<b>propertyToMapMap</b>
</field>
<field map-id="myTestMapping">
<a>propertyToMapToNullMap</a>
<b>nullPropertyToMapMap</b>
<b-hint>java.util.HashMap</b-hint>
</field>
<field map-id="myCustomTestMapping">
<a>propertyToCustomMap</a>
<b>propertyToCustomMapMap</b>
</field>
</mapping>
The Class Level map backed mappings can also be used as a standard mapping.
For this dozer has a new API. In addition to the source and destination classes you
can now pass in the map reference Id.
// Example 1
PropertyToMap ptm = new PropertyToMap();
ptm.setStringProperty("stringPropertyValue");
ptm.addStringProperty2("stringProperty2Value");
Map map = Mapper.map(ptm, HashMap.class, "myTestMapping");
// Example 2
CustomMap customMap = mapper.map(ptm, CustomMap.class, "myCustomTestMapping");
// Example 3
CustomMap custom = new CustomMap();
custom.putValue("myKey", "myValue");
Mapper.map(ptm, custom, "myCustomTestMapping");
63
Map Backed Property Mapping
64
Proxy Objects
Proxy Objects
Overview
Dozer supports mappings done on proxy objects. This is typically the case when
using persistence framework, which supports sophisticated features like lazy-
loading. In this case application is working with fake objects, containing the real
objects encapsulated. Implementation of proxies is dependant on the technology you
use. Generally speaking, there are two popular libraries for creating Java proxies
(Cglib and Javassist). However, how particular framework makes uses of them could
also vary. Dozer offers by default a generic way to handle simple proxy scenarios,
both Javassist and Cglib. However it is strongly recommended to tune proxy
handling behavior for your particular scenario.
Configuration
Proxy implementation is set-up by modifying configuration file. Currently, besides of
default behavior, Hibernate and No-Proxy modes are supported. For the full list of
the implementations, see the list of org.dozer.util.DozerProxyResolver interface
implementations. The list could be retrieved from JavaDocs.
In case you do not map proxied objects - use NoProxy resolver, which imposes
minimum performance overhead.
Custom Scenarios
For custom scenarios it is possible to provide your own implementation of
org.dozer.util.DozerProxyResolver interface. It is configured in the same way as the
standard classes.
65
Custom Converters
Custom Converters
Custom converters are used to perform custom mapping between two objects. In the
Configuration block, you can add some XML to tell Dozer to use a custom converter
for certain class A and class B types. When a custom converter is specified for a
class A and class B combination, Dozer will invoke the custom converter to perform
the data mapping instead of the standard mapping logic.
Custom converters are shared across mapping files. This means that you can define
them once in a mapping file and it will be applied to all class mappings in other
mapping files that match the Class A - Class B pattern. In the example below,
whenever Dozer comes across a mapping where the src/dest class match the
custom converter definition, it will invoke the custom converter class instead of
performing the typical mapping.
66
Custom Converters
</mappings>
Custom converters can also be specified at the individual field level. In the example
below, Dozer will invoke the custom converter to perform the field mapping.
<mapping>
<class-a>org.dozer.vo.SimpleObj</class-a>
<class-b>org.dozer.vo.SimpleObjPrime2</class-b>
<field custom-converter="org.dozer.converters.StringAppendCustomConverter">
<a>field1</a>
<b>field1Prime</b>
</field>
</mapping>
Custom converter 'instances' can be reused at the individual field level. In the
example below, Dozer will invoke the custom converter to perform the field mapping.
<mapping>
<class-a>org.dozer.vo.SimpleObj</class-a>
<class-b>org.dozer.vo.SimpleObjPrime2</class-b>
<field custom-converter-id="CustomConverterWithId">
<a>field1</a>
<b>field1Prime</b>
</field>
</mapping>
DozerBeanMapperBuilder#withCustomConverter(..) method.
67
Custom Converters
</map>
</property>
</bean>
</beans>
Note: Custom Converters get invoked when the source value is null , so you need
to explicitly handle null values in your custom converter implementation.
CustomConverters can also be injected into the Mapper if you need to do some
manipulation with them before they are used in dozer.
68
Custom Converters
<value>dozerBeanMapping.xml</value>
<value>injectedCustomConverter.xml</value>
</list>
</property>
<property name="customConverters">
<list>
<ref bean="customConverterTest" />
</list>
</property>
</bean>
<!-- custom converter -->
<bean id="customConverterTest" class="org.dozer.converters.InjectedCustomConverter"
>
<property name="injectedName">
<value>injectedName</value>
</property>
</bean>
</beans>
<converter type="org.dozer.converters.StringAppendCustomConverter">
<class-a>[Lorg.dozer.vo.SimpleObj;</class-a>
<class-b>java.lang.String</class-b>
</converter>
<converter type="somePackage.SomeCustomConverter">
69
Custom Converters
<class-a>somePackage.SomeObject</class-a>
<class-b>java.lang.Integer</class-b>
</converter>
<mapping>
<class-a>org.dozer.vo.BeanA</class-a>
<class-b>org.dozer.vo.BeanB</class-b>
<field custom-converter="org.dozer.converters.MathOperationConverter" custom-conve
rter-param="+">
<a>amount</a>
<b>amount</b>
</field>
</mapping>
Configurable custom converter should be used when you have similar behaviour in
many cases, which can be parametrized, but the number of combinations is too high
to do simple Custom Converter subclassing.
70
Custom Converters
public NewDozerConverter() {
super(String.class, Boolean.class);
}
Note that Java 5 Generics are supported and you do not need to cast source object
to desired type as previously.
71
Custom Converters
public Converter() {
super(List.class, Map.class);
}
<...>
72
Custom Bean Factories
Next, in your Dozer mapping file(s) you just need to specify a bean-factory xml
attribute for any mappings that you want to use a custom factory.
In the following example, the SampleCustomBeanFactory will be used to create any new
instances of the InsideTestObjectPrime java bean data object.
<mapping>
<class-a>com.example.vo.InsideTestObject</class-a>
<class-b bean-factory="com.example.factories.SomeCustomBeanFactory">
com.example.vo.InsideTestObjectPrime
</class-b>
</mapping>
If your factory looks up beans based on a different id than class name, you can
specify a factory-bean-id xml attribute. At runtime the specified factory-bean-id will
be passed to the factory instead of class name.
<mapping>
<class-a>com.example.vo.InsideTestObject</class-a>
<class-b bean-factory="com.example.factories.SomeCustomBeanFactory" factory-bean-id
="someBeanLookupId">
com.example.vo.InsideTestObjectPrime
73
Custom Bean Factories
</class-b>
</mapping>
<configuration>
<stop-on-errors>true</stop-on-errors>
<wildcard>true</wildcard>
<bean-factory>com.example.factories.SomeDefaultBeanFactory
</bean-factory>
</configuration>
Bean factories can also be specified at the mapping level. The specified factory
would be used for class-a and class-b .
<mapping bean-factory="com.example.factories.SomeCustomBeanFactory">
<class-a>com.example.vo.TestObject</class-a>
<class-b>com.example.vo.TestObjectPrime</class-b>
</mapping>
<beans>
<bean id="org.dozer.Mapper" class="org.dozer.DozerBeanMapper">
<property name="mappingFiles">
<list>
<value>dozerBeanMapping.xml</value>
</list>
</property>
<property name="factories">
<map>
<!-- the key matches the name of the factory in the
dozerBeanMapping.xml file -->
<entry key="org.dozer.factories.SampleCustomBeanFactory">
<ref bean="sampleCustomBeanFactory" />
74
Custom Bean Factories
</entry>
<!-- more factories can be supplied with additional
entry's -->
</map>
</property>
</bean>
<bean id="sampleCustomBeanFactory" class="org.dozer.factories.SampleCustomBeanFact
ory" />
</beans>
By defining your factories as Spring beans you can then inject them into the Mapper
instance.
75
Custom Create Methods
<mapping>
<class-a create-method="someCreateMethod">
org.dozer.vo.InsideTestObject
</class-a>
<class-b>org.dozer.vo.InsideTestObjectPrime</class-b>
<field>
<a>label</a>
<b>labelPrime</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>createMethodType</a>
<b create-method="someCreateMethod">createMethodType</b>
</field>
</mapping>
It is also possible to reference different class with static factory method. This is done
by providing fully qualified type name and method name separated by dot.
<b create-method="org.dozer.factory.Factory.create">field</b>
76
Custom get() set() Methods
<field>
<a>fieldAccessible</a>
<b is-accessible="true">fieldAccessible</b>
</field>
<field>
<a set-method="placeValue" get-method="buildValue">value</a>
<b>value</b>
</field>
<!-- we can not map a ArrayList to a String, hence the one-way mapping -->
<field type="one-way">
<a>integerStr</a>
<b set-method="addIntegerToList">integerList</b>
</field>
77
Custom get() set() Methods
Sometimes set() methods can be overloaded. In order to chose the correct one you
can add the class type as a parameter.
<field>
<a>overloadGetField</a>
<b set-method="setOverloadSetField(java.util.Date)">
overloadSetField
</b>
</field>
<field>
<a>appleComputers</a>
<b set-method="addComputer" type="iterate">computers</b>
<b-hint>org.dozer.vo.AppleComputer</b-hint>
</field>
<field>
<a set-method="addCar" get-method="myIterateCars" type="iterate">iterateCars</a>
<b set-method="addIterateCar" type="iterate">iterateCars</b>
<a-hint>org.dozer.vo.Car</a-hint>
<b-hint>org.dozer.vo.Car</b-hint>
</field>
78
Expression Language
Expression Language
Usage
Dozer provides optional support for standard java expression language (javax.el).
Current support for expressions is start-up time only. Expressions are not resolved
during each mapping, but rather during Xml mapping file loading procedure. Each
attribute or node value can contain a valid EL expression $\{}.
You can define global variables for the mapper in variables configuration block.
<configuration>
<wildcard>true</wildcard>
<variables>
<variable name="type_name">org.dozer.sample.MyType
</variable>
</variables>
<mapping>
<class-a>${type_name}</class-a>
</mapping>
</configuration>
Enabling
EL support is an optional feature. If it is not enable it does not affect mapping
performance neither it requires additional Jar dependencies to your project.
79
Logging
Logging
The logging facade framework in Dozer is SLF4J. It replaced Commons Logging,
which was used in project previously until version 5.3.
80
Event Listening
Event Listening
By implementing the DozerEventListener interface dozer allows you to listen to 4
different events:
mappingStarted
mappingFinished
preWritingDestinationValue
postWritingDestinationValue
A DozerEvent object is passed into these callback methods which stores information
about the ClassMap , FieldMap , source object, destination object, and destination
value. This will allow you to extend Dozer and manipulate mapped objects at run-
time. The interface is shown below:
The listeners that you create can be injected into the Mapper using an IOC like
Spring or set directly during Mapper instance configuration using
DozerBeanMapperBuilder#withEventListener(..) method. Below is an example using
81
Event Listening
</list>
</property>
</bean>
<bean id="eventTestListener" class="org.dozer.event.EventTestListener" />
</beans>
82
Statistics
Statistics
If you enable statistics, Dozer will collect a number of runtime mapping metrics.
These statistics are global and can be accessed via the GlobalStatistics object. The
statistics are also available via JMX. Dozer is distributed with a fully functional JMX
DozerStatisticsControllerMBean.
Based on our profiling numbers, the overhead of enabling statistics is roughly 3-5%.
# of DozerBeanMapper objects
Mapper Instances Count created. This should be a low
number
83
Statistics
84
JMX Integration
JMX Integration
Dozer can be managed via JMX. The Dozer distibution contains fully functional JMX
MBeans. These MBeans can be found in the org.dozer.jmx package.
Dozer auto registers these JMX Beans with the PlatformMBeanServer. You can
suppress this behavior with the following Dozer configuration property:
dozer.autoregister.jmx.beans = false
Note that JMX MBeans are potential source of memory leaks. MBeans should be
disposed properly when application is stopped or restarted as in most of todays Web
Containers there is no full JVM restart. The proper way to unregister all Dozer JMX
Beans is to call destroy() method on DozerBeanMapper object.
85
JMX Integration
86
Metadata Query Interface
The following sections will give some code examples how to use the mapping query
interfaces. The most important interface in the whole process is
org.dozer.metadata.MappingMetadata . An instance can be acquired by calling the
try {
ClassMappingMetadata classMappingMetadata =
87
Metadata Query Interface
mapMetadata.getClassMapping(ClassA.class, ClassB.class);
} catch (MetadataLookupException e) {
// couldn't find it
}
try {
FieldMappingMetadata fieldMetadata = classMetadata.getFieldMappingBySource("fieldA")
;
// Destination: fieldB
System.out.println("Destination: " + fieldMetadata.getDestinationName());
} catch (MetadataLookupException e) {
// couldn't find it
}
For extensive documentation on the different interfaces please refer to the JavaDoc.
88
Spring Integration
Note that this Factory Bean supports Spring Resources, which means that you could
load mapping Xml files by classpath mask for example.
<bean class="org.dozer.spring.DozerBeanMapperFactoryBean">
<property name="mappingFiles" value="classpath*:/*mapping.xml" />
<property name="customConverters">
<list>
<bean class="org.dozer.converters.CustomConverter" />
</list>
</property>
<property name="eventListeners">
<list>
<bean class="org.dozer.listeners.EventListener" />
</list>
</property>
<property name="factories">
<map>
<entry key="id" value-ref="bean-factory-ref" />
</map>
</property>
</bean>
89
Spring Integration
<property name="mappingFiles">
<list>
<value>dozer-global-configuration.xml</value>
<value>dozer-bean-mappings.xml</value>
<value>more-dozer-bean-mappings.xml</value>
</list>
</property>
</bean>
90
JAXB and XMLBeans
<mapping>
<class-a>org.dozer.vo.TestObject</class-a>
<class-b bean-factory="org.dozer.factory.JAXBBeanFactory">
org.dozer.vo.jaxb.employee.Employee
</class-b>
<field>
<a>name</a>
<b>firstName</b>
</field>
<field>
<a>street</a>
<b>address.street</b>
</field>
</mapping>
Mapping XMLBeans
Dozer has support for mapping POJOs to XMLBeans objects. Use the
XMLBeanFactory for any XMLBeans you want created. This factory will also be used
for mapping any fields that need to be instantiated in a deep mapping that are not
regular POJOs but are XMLBeans.
<mapping wildcard="false">
<class-a>org.dozer.vo.TestObject</class-a>
<class-b bean-factory="org.dozer.factory.XMLBeanFactory">
org.dozer.vo.GetWeatherByZipCodeDocument
</class-b>
<field>
<a>one</a>
91
JAXB and XMLBeans
<b>GetWeatherByZipCode.zipCode</b>
</field>
</mapping>
assertEquals(to.getOne(), doc.getGetWeatherByZipCode().getZipCode());
assertEquals(res.getGetWeatherByZipCode().getZipCode(), to2.getOne());
92
FAQ
Is Dozer recursive?
Will the getter and setter methods be invoked when fields are mapped?
Which types of data mappings do I need a custom xml mapping definition for?
If my src and dest object have all matching attribute names, do I need to specify
any xml mapping definitions at all?
For mappings that require an xml mapping definition, is the mapping definition
bi-directional, or do I need 2 xml definitions if I need to map the two objects both
ways?
How can I tell if Dozer is initializing correctly and loading my xml mapping files?
93
FAQ
Advanced
Can I implement custom mapping logic between 2 data types and have Dozer
invoke this custom logic when it’s performing mappings?
Can I map one field into another field that is nested n layers deep in the
destination object?
Some of my data objects don’t have public constructors. Does Dozer support
this use case?
When mapping collections, how do I tell Dozer what type of data objects I want
in the destination collection?
How can I tell Dozer to bypass mapping null or empty string values?
Should I write unit tests for data mapping logic that I use Dozer to perform?
Is it better to have 1 large xml mapping file or to have multiple smaller mapping
files?
94
FAQ
Answers
Is Dozer recursive?
Yes. Dozer recursively maps the entire object graph for all fields.
95
FAQ
96
FAQ
97
FAQ
Performance is going to depend on the complexity of the use case and the number
of fields mapped. In our performance tests for "average" mapping scenarios, the
class mapping times vary from 1/8 of a millisecond to 2 milliseconds. This roughly
equates to 50 - 450 field mappings per millisecond. However, the number of
variables in any decent benchmark makes it almost impossible to transfer these
results into reasonable conclusions about the performance of your own application.
Your application is different and you will have unique use cases.
If you want to see actual Dozer runtime mapping statistics within the context of a
system/application, you can enable Dozer statistics. This would be a good way to
determine actual mapping times as a percentage of overall system performance. The
best way to view the stats is via the Dozer JMX Beans. With the 3.2 release, these
JMXBeans are auto registered with the platform mdb server. JConsole is a good way
to easily view the MBeans.
Based on our profiling numbers, the overhead of enabling statistics is roughly 3-5%.
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>${dozer.version}</version>
</dependency>
98
FAQ
Yes, dozer does not burn any fossil fuels and is within the EPA’s recommended
emissions.
<custom-converters>
<converter type="org.dozer.converters.SomeCustomConverter">
<class-a>org.dozer.vo.SomeCustomDoubleObject</class-a>
<class-b>java.lang.Double</class-b>
</converter>
</custom-converters>
<field>
<a>someNestedObj.someOtherNestedObj.someField</a>
<b>someOtherField</b>
</field>
99
FAQ
custom converter for mapping between the complex type and the single field. This
way, you could handle the custom logic required to map the three fields into the
single one within the custom converter.
<field>
<a>usernames[0]</a>
<b>username1</b>
</field>
<mapping map-id="myTestMapping">
<class-a>org.dozer.vo.map.SomeComplexType</class-a>
<class-b>java.util.Map</class-b>
<field>
<a>stringProperty2</a>
<b key="myStringProperty">this</b>
</field>
</mapping>
100
FAQ
<field>
<a>fieldA</a>
<b is-accessible="true">fieldB</b>
</field>
Dozer has support for mapping POJOs to JAXB objects. Use the JAXBBeanFactory
for any JAXB objects you want created.
101
FAQ
No, but we think it would be a great addition. It would be very powerful to be able to
graphically map 2 objects and have the custom xml definitions auto generated, along
with being able to visually view a mapping definition. If anyone has expertise in
creating eclipse plugins and is interested on working on this feature, please let us
know!
<field>
<a>someList</a>
<b>otherList</b>
<b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint>
</field>
You can bypass the mapping of empty String values by specifying map-empty-
string="false". If this is specified, the dest field mapping is bypassed at runtime and
the destination value setter method will not be called if the src value is an empty
String. This can be specified at the mapping or class level
102
FAQ
It seems to work best if these assembler type of classes are "dumb" and are only
responsible for simply copying data from the source object into the destination
object. Any complex postprocessing business logic that needs to be performed on
the destination object can be done at a higher level in classses that have more
responsibility.
The following is a simple example of an assembler type class that uses Dozer for its
underlying implementation.
103
FAQ
For existing systems that are wanting to migrate to Dozer, we recommend first
encapsulating any existing hand coded data mapping into an assembler type of class
and write unit tests for it. Then switch out the hand coded mapping logic with Dozer
and the unit tests will be your safety net. The migration to Dozer can be incremental
and this is probably the best strategy for exisiting systems.
Regardless of whether or not you use Dozer, unit testing data mapping logic is
tedious and a necessary evil, but there is a trick that may help. If you have an
assembler that supports mapping 2 objects bi-directionally, in your unit test you can
do something similar to the following example. This also assumes you have done a
good job of implementing the equals() method for your data objects. The idea is that
if you map a source object to a destination object and then back again, the original
src object should equal the object returned from the last mapping if fields were
mapped correctly. In the test case, you should populate all the possible fields in the
original source object to ensure that all of the fields are accounted for in the mapping
logic.
104
FAQ
It is also good practice to verify that your assembler handles null values properly. In
the following test case none of the source fields are populated. If the assembler
doesn’t properly handle null values, an exception will be thrown when the assembler
is invoked.
105
FAQ
The best way to view the runtime stats is via the Dozer JMX Beans. These
JMXBeans are auto registered with the platform mdb server at startup. JConsole is a
good way to easily view the MBeans.
To debug individual field mappings between classes, set the logging level
"org.dozer.MappingProcessor=DEBUG". For example, if you are using log4j you
would add the following entry to your log4j configuration file
"log4j.category.org.dozer.MappingProcessor=DEBUG". This will show you every
field mapping that Dozer performs along with the actual source and destination
values. You will see output similar to the following….
106
FAQ
107
Examples
Examples
There are some sample mapping files under \{dozer.home}/src/test/resources. These
mapping files are used by the Dozer unit tests.
108
v5 to v6
<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-osgi dropped
You no longer need to use the below, if you are running in an OSGi environment:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer-osgi</artifactId>
<version>5.5.1</version>
</dependency>
109
v5 to v6
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
<version>6.0.0</version>
</dependency>
110
v6.0.0 to v6.1.0
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.ne
t/schema/beanmapping.xsd">
To:
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://
dozermapper.github.io/schema/bean-mapping.xsd">
<beans xmlns="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/beans http://www.springframework.org/
schema/beans/spring-beans-4.3.xsd
http://dozer.sourceforge.net/schema/dozer-spring http://dozer.sourceforge.n
et/schema/dozer-spring.xsd">
To:
<beans xmlns="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="
111
v6.0.0 to v6.1.0
http://www.springframework.org/schema/beans http://www.springframework.org/
schema/beans/spring-beans-4.3.xsd
http://dozermapper.github.io/schema/dozer-spring http://dozermapper.github.
io/schema/dozer-spring.xsd">
Deprecated:
mapper.map(a, b);
Recommended:
mapper.map(a, b);
Dozer project does not advise to use JVM singletons. Please use your DI container
to manage single instance of the Mapper if required. The following code can be used
to create a Mapper with default configuration:
112
v6.0.0 to v6.1.0
Dozer is moving away from having JVM-global state. This means that some internal
API like BeanContainer is not available anymore via singleton references, i.e.
BeanContainer.getInstance() does not exist. If you were using this or any other code
that is reworked, please let us know. Most likely you developed DozerModule . We
would like to know more about real-world use cases to build convenient public API
for modules developers.
Deprecated:
Recommended:
org.dozer.stats
org.dozer.jmx
org.dozer
To:
com.github.dozermapper.protobuf
113
v6.0.0 to v6.1.0
org.dozer.spring
To:
com.github.dozermapper.spring
114
Installation
Prerequisites
The Plugin currently depends on
Compatibility
Plugin is supported and been tested on the following IDEs
Eclipse 3.6
Installation
The Dozer Plugin-feature can be installed and updated using the Eclipse Update
Manager.
http://dozer.sourceforge.net/eclipse-plugin
Alternatively you can download the package at sourceforge and unzip it in your
eclipse installation folder. You might have to enable the Plugin after starting Eclipse.
This can be done at Help > Software Updates > Manage Configuration.
After installation is done you should see a little red dozer-icon on all your mapping-
xml files.
115
Installation
116
Usage
117
via XML
Content Assist
118
via XML
119
via XML
Validation
The Dozer Plugin validates the Mapping to find out if the mapped class do exist and
if the mapped fields are accessible.
120
via XML
121
via Editor
Configuring mappings
Every classmapping is listed in the "Mapping" Tab. Mappings of classes and fields
can be added by Popup menu or the action-buttons at the top. On the right side the
mappings can be configured. Every Attribute or Element in the XML file is shown for
editing.
122
via Editor
123