Dozer Mapping

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. This blog will explain you how to convert one Java Bean into another Java Bean by using context type mapping[Dozer mappings], also you can convert one variable type into another variable type by defining them into XML file.

Dozer supports different type of mappings:
1. Simple property mapping
2. Complex type mapping
3. Bi-directional mapping
4. implicit-explicit mapping
5. Recursive mappings
Dozer supports mapping for collection attributes, which is required to element level mapping.
Many a times we need a context based mapping with Dozer so as to control number of fields conversion. Let’s take an example of converting

SourceClass to DestinationClass.

public class SourceClass {                         
	private String sourceStringForInteger;
	private String sourceStringForLong; 
	private String sourceStringForint;
	private String sourceStringForString;
	private List sourceCol;
	…
}

public class DestinationClass {
	private Integer sourceStringForInteger;
	private Long sourceStringForLong;
	private int sourceStringForint;
	private String sourceStringForString;
	private List destCol;
	…
}

You can see SourceClass contains sourceCol variable of type List, which we are converting into destCol variable of type List in DestinationClass.
Here sourceCol is an object type of SourceChildClass and destCol is an object of DestinationChildClass.

public class SourceChildClass { 
	private String prop1; 
	private String prop2; 
	private String prop3; 
	…
}

public class DestinationChildClass {
	private Integer prop1;
	private Integer prop2;
	private Integer prop3;
	…
}

Usecase 1 [Simple conversion of source object into destination object.]

We will use map-id attribute to name the cases.
In one service call/conversion we want to convert SourceClass into DestinationClass (say caseA)

<mapping map-id="caseA">
      <class-a>package.SourceClass</class-a>
      <class-b>package.DestinationClass</class-b>
      <field>
       <a>sourceCol</a>
       <b>destCol</b>
       <a-hint>package.SourceChildClass</a-hint>
       <b-hint>package.DestinationChildClass</b-hint>
      </field>
</mapping>

In this mapping

1. Tag <class-a> value source class
2. Tag <class-b> value destination
3. Tag <a> value collection variable in source class
4. Tag <b> value collection variable in destination class
5. Tag <a-hint> Object type of collection defines as tag <a> value.
6. Tag <b-hint> Object type of collection defines as tag <b> value.
7. Other SourceClass fields will implicitly convert into DestinationClass fields irrespective of there data types, like sourceStringForInteger a variable of String type in SourceClass, dozer will convert this variable into Integer type in DestinationClass.

Let’s see we want to exclude sourceStringForInteger variable define SourceClass (say caseB).

<mapping map-id="caseB">
      <class-a>package.SourceClass</class-a>
      <class-b>package.DestinationClass</class-b>
      <field>
       <a>sourceCol</a>
       <b>destCol</b>
       <a-hint>package.SourceChildClass</a-hint>
       <b-hint>package.DestinationChildClass</b-hint>
      </field>

<field-exclude>	
         	<a> sourceStringForInteger </a>
         	<b> sourceStringForInteger </b>
          </field-exclude>
   </mapping>

In this mapping
Add tag and define variable names, which you want to exclude.

Let’s see how code look like. sourceClass is an object of type SourceClass which has to be converted into DestinationClass

DestinationClass destinationClass = (DestinationClass) mapper.map (sourceClass, DestinationClass.class,"caseA");

Definition of mapper is done as bean in Spring.

Here we pass a third string argument indicating the name of the mapping to be used by the Dozer. This argument will be used for converting from SourceClass to DestinationClass.
While doing reverse conversion means conversion form DestinationClass to SourceClass we have to add PRIME to name of mapping.

SourceClass sourceClass = (SourceClass) mapper.map (destinationClass, SourceClass.class,"caseAPRIME");

Usecase 2 [Complex conversion of source object into destination object.]

Let’s see a complex scenario. Say we want to exclude prop1 variable defined in SourceChildClass to be converter for caseA. So for this we have to tell the dozer to use a different mapping while converting the object belonging to collection. We could name that mapping as collCaseA, and in the field tag we will use map-id to indicate the name.

<mapping map-id="caseA">
      <class-a>package.SourceClass</class-a>
      <class-b>package.DestinationClass</class-b>
       <! -- Uses mapping named childCaseA for conversion of objects in the collection -- >
      <field map-id="collCaseA">
       <a>sourceCol</a>
       <b>destCol</b>
       <a-hint>package.SourceChildClass</a-hint>
       <b-hint>package.DesctinationChildClass</b-hint>
      </field>
 </mapping>

 <mapping map-id="collCaseA">
      <class-a>package.SourceChildClass</class-a>
      <class-b>package.DestinationChildClass</class-b>
      <field-exclude>
         <a>prop1</a>
         <b>prop1</b>
      </field-exclude>
 </mapping>

In this mapping
The change done is from Usecase-1, CaseA in adding new mapping to define exclude specific field from collection conversion under < mapping map-id="collCaseA"> tag.

Similarly for caseB we want to exclude prop2 variable define in SourceChildClass, so we call it as collCaseB.

<mapping map-id="caseB">
  <class-a>package.SourceClass</class-a>
  <class-b>package.DestinationClass</class-b>
  <field map-id="collCaseB">
   <a>sourceCol</a>
   <b>destCol</b>
   <a-hint>package.SourceChildClass</a-hint>
   <b-hint>package.DestinationChildClass</b-hint>
  </field>
  <field-exclude>
   <a>sourceStringForInteger</a>
   <b>sourceStringForInteger</b>
  </field-exclude>
</mapping>

<mapping map-id="collCaseB">
    <class-a>package.SourceChildClass</class-a>
    <class-b>package.DestinationChildClass</class-b>
    <field-exclude>
      <a>prop2</a>
      <b>prop2</b>
    </field-exclude>
</mapping>

In this mapping
The change done is from Usecase-1, CaseB in adding new mapping to define exclude specific field from collection conversion under <mapping map-id="collCaseB"> tag.

Conversion code would remain same for Usecase 2 as in Usecase 1.

Conclusion: You have seen various cases of context based mapping conversion. For more information you can refer following resources.
Deep Mappings
http://dozer.sourceforge.net/
If you have any specific question, please comment back. I will try to reply with answer.

Comments (16)

  1. Maarten Winkels - Reply

    September 25, 2007 at 9:40 am

    Hi Amit,

    Very interesting read! I've looked at Dozer a few times, but never found a good use case. Normally writing a converter class seemed so much simpler than adding a new framework, learning to use it and maintaining the XML configuration. What are the situations that you feel Dozer is a viable alternative to writing the classes your self?
    I wasn't aware of the type conversion possibilities of the framework at the time. Is this a new feature?

    Regards, Maarten

    • Sam - Reply

      September 29, 2011 at 1:22 pm

      Well I used Dozer for one of my implementation where we were using protocol to protocol transformation for one of our Identity provisioning implementation. We had a use case where we were receiving a SPML 2.0 standard message from one ERP and we need to convert the same to Oracle Identity Manager SPML 2.0 standard. As both these ERP and OIM extended the SPML 2.0 Extension API and are making heavy use of same. we were suppose to do lots of custom code to make this attribute to attribute mapping, as we a product based company we need to implement this in more generic way so that we can make the mapping in declarative way rather in Scala code. So I used modified Dozer [some code/component of Dozer API are been replaced by Scala implementation] to address the requirement.

  2. Venkat - Reply

    October 31, 2007 at 7:19 pm

    Dozer will be helpful in case if your project/system has many value objects(VO) & DTO objects. You dont need to write a lengthy method in your Java Bean, Dozer will be taking care of that with help of configuration

  3. Wil Palen - Reply

    October 15, 2008 at 5:18 pm

    Dozer is far from mature yet. If you have a somewhat fancy domain model that uses inheritance and you try to map collections of a supertype that contains different specialized instances Dozer falls flat on its face.

    Also, it does not handle Number Number conversions gracefully

    In general, it seems to be unable to work with inheritance

    This is a big disappointment for a product that carries a version number of 4.2.1

    Lost a couple of days on my project because of these shortcomings. In the end we couldn't use it.

  4. LP - Reply

    August 24, 2009 at 8:46 pm

    I'd say the biggest advantage of using Dozer is that it automatically produces mapping to both directions. If you don't need that you might want to consider writing the mapper classes yourself. Dozer is kind of configuration hell.

  5. Bruce - Reply

    December 29, 2009 at 11:43 pm

    Where can I go to find help with Dozer. I have a case where the source and destination classes both have a feild of the same type (MyDate) with setters and getters. Since MyDate does not have a no-argument constructor, Dozer throw and exception. I have not be able to find any information about this.

  6. sishir kumar - Reply

    January 24, 2011 at 6:37 am

    This blog is very helpfull to understand about dozer..... Thanks a lot..

  7. tr3pek - Reply

    December 9, 2011 at 12:48 pm

    Hi,

    Does Dozer handles cases, when we map from one class which is exact reflcecition of DB table with complex parameter key, eg:
    DataObject {
    int key_part1;
    String key_part2;
    ...
    }
    then at higher tier, we have some BO:
    BusinessObject {
    ComplexKey key;
    ...
    }
    and some key class:
    ComplexKey {
    int key_part1;
    String key_part2;
    }

  8. Tom - Reply

    December 21, 2011 at 1:11 am

    Yes it does, with this simple mapping configuration (don't forget the getters and setters in your classes):

    org.dozerTest.DataObject
    org.dozerTest.BusinessObject

    key_part1
    key.key_part1

    key_part2
    key.key_part2

  9. Tom - Reply

    December 21, 2011 at 1:13 am

    oops... html problems:

    Yes it does, with this simple mapping configuration (don’t forget the getters and setters in your classes):

    <mapping>
    <class-a>org.dozerTest.DataObject</class-a>
    <class-b>org.dozerTest.BusinessObject</class-b>
    <field>
    <a>key_part1</a>
    <b>key.key_part1</b>
    </field>
    <field>
    <a>key_part2</a>
    <b>key.key_part2</b>
    </field>
    </mapping>

  10. Ronald - Reply

    July 30, 2012 at 9:53 am

    Hi, Im new to dozer, im mapping excel file to my java entity bean flawlessly. the thing is, i would like to display the source value to my page if theres an invalid mapping. for example, i accidentally put "ABC" to destination "integer". there will be an conversionexception-thats ok and id like to display "Cannot convert "ABC" to integer" or somewhere along that line.

  11. Shalini - Reply

    January 24, 2013 at 1:32 pm

    Hi... Thanks for the blog. Can you help me with dozer mapping of a String and an object having a field of type String?When I am trying to map by:

    User
    UserDTO

    userPassword.password
    userPassword

    I get the following error:

    Illegal object type for the method 'setUserPassword'.
    Expected types:
    com.domain.UserPassword
    Actual types:
    java.lang.String

  12. Rama - Reply

    June 20, 2014 at 4:49 am

    Hi have a scenario and need your valuable help in fixing it.

    I want to integrate springs with dozer. Let me say I have a spring map bean in my xml file and how can I use this bean in my dozer custom converter?

  13. Mohammed - Reply

    April 20, 2015 at 5:47 pm

    If the sourceclass and destination has an object reference with same structure but belong to different package. Will the dozer be able to map it just by looking at the name as both having same name?

  14. Anil - Reply

    July 23, 2015 at 9:43 pm

    Hi,
    Can someone help to map following scenario-
    In source class i have 4 fields like
    string field1
    string field2
    string field3
    But in destination I have only 2 fields like -
    string field1
    string field2
    So how I can do this mapping using dozer.

  15. Andrew Jardine - Reply

    October 19, 2015 at 11:46 pm

    Hey Amit,

    I'm having a problem with deep mapping of generics. Your tutorial here looks very similar to what I am trying to do, except that my nested object is a List rather than a direct object itself. I'm using Doze 5.5.1 and I have tried with both as well as with and . Neither case seems to work.

    Can you help me understand how I can (deep) map a List of objects?

Add a Comment