简体   繁体   中英

Dozer mapping for complex objects

I have 2 POJOs as shown below:

package com.main.java.src;

    public class SourceObj {

    protected String name;
    ...
    ...
    10 String objects

    protected Addresses addresses; 

    ...
    ...
    getter and setter for all fields

    }
---------    
package com.java.main.src;

    public class Addresses {
     protected List<Address> address;
    ...
    getters and setters

}

    package com.main.java.src;

    public class Address {
       protected String city;

       protected List<Contact> contact;

    ...

    getters & setters
    }

-----
package com.main.java.dest;
    public class DestObj {

    protected String name;
    ...
    ...
    10 String objects

    protected Addresses addresses; 

    ...
    ...
    getter and setter for all fields

    }

----------------
package com.main.java.dest;

    public class Addresses {
     protected List<Address> address;
    ...
    getters and setters
    }

package com.main.java.dest;
    public class Address {
       protected String city;

       protected List<Contact> contact;

    ...

    getters & setters
    }

Now i have the dozer-configuration.xml as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    <mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://dozer.sourceforge.net http://dozer.sourceforge.net/schema/beanmapping.xsd">
        <configuration>
            <stop-on-errors>true</stop-on-errors>
            <trim-strings>true</trim-strings>
            <relationship-type>non-cumulative</relationship-type>       
        </configuration>

        <mapping>
            <class-a>com.main.java.src.SourceObj</class-a>
            <class-b>com.main.java.dest.DestObj</class-b>
            <field>
                <a>addresses.address</a>
                <b>addresses.address</b>
                <a-hint>com.main.java.src.Address</a-hint>
                <b-hint>com.main.java.dest.Address</b-hint>
            <field> 
        </mapping>
    </mappings>

Now the above mapping copies fields like name from SourceObj to DestObj, but not able to map List of Address from src package to List of Address of dest package. Again inside Address object, there is a list of Contact object.

One solution i found is to write a custom converter which will copy primitive field values one by one and then all objects from one list to another destination list.

But I am looking for a solution in dozer-configuration.xml.

After the above xml mappings, i am getting below exception:

MapId: null
  Type: null
  Source parent class: com.main.java.src.SourceObj
  Source field name: addresses.address
  Source field type: class java.util.ArrayList
  Source field value: [com.main.java.src.Address@1b65d51d]
  Dest parent class: com.main.java.dest.DestObj
  Dest field name: addresses.address
  Dest field type: java.util.List

java.lang.NullPointerException: null
    at org.dozer.util.ReflectionUtils.invoke(ReflectionUtils.java:329) ~[dozer-5.5.1.jar:?]
    at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.writeDeepDestinationValue(GetterSetterPropertyDescriptor.java:268) ~[dozer-5.5.1.jar:?]
    at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.setPropertyValue(GetterSetterPropertyDescriptor.java:96) ~[dozer-5.5.1.jar:?]
    at org.dozer.fieldmap.FieldMap.writeDestValue(FieldMap.java:96) ~[dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.writeDestinationValue(MappingProcessor.java:939) ~[dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:368) ~[dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.mapField(MappingProcessor.java:307) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:267) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.mapToDestObject(MappingProcessor.java:216) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.createByCreationDirectiveAndMap(MappingProcessor.java:196) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.mapGeneral(MappingProcessor.java:170) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:104) [dozer-5.5.1.jar:?]
    at org.dozer.MappingProcessor.map(MappingProcessor.java:99) [dozer-5.5.1.jar:?]
    at org.dozer.DozerBeanMapper.map(DozerBeanMapper.java:120) [dozer-5.5.1.jar:?]

Please advise with the solution for this case.

Dozer will map anything with the same name and type automatically. When the fields you want to map have different names, you must explicitly tell Dozer in the mapping which fields to map to each other. In the question above, the AddressSrc and AddressDest are fields with different names. Therefore, you must explicitly tell Dozer to map those two fields to each other.

<mapping>
    <class-a>SourceObj</class-a>
    <class-b>DestObj</class-b>    
    <field>
        <a>addressesSrc</a>
        <b set-method="customSetMethodName">addressesDest</b>
    </field>  
</mapping>

You may need additional mapping instructions to get the result you ultimately want. However, this is the missing mapping piece you need to get Dozer to map these two fields since they have different names.

I have found the answer after much trial and error. Please refer the below solution.

<mapping>
  <class-a>com.java.main.src.SourceObj</class-a>
  <class-b>com.java.main.dest.DestObj</class-b>
  <field>><!-- java.util.List to java.util.List -->
     <a is-accessible="true">addresses.address</a>
     <b is-accessible="true">addresses.address</b>
     <a-hint>com.java.main.src.Address</a-hint>
     <b-hint>com.java.main.dest.Address</b-hint>
  </field>
</mapping>

<mapping>
  <class-a>com.java.main.src.Address</class-a>
  <class-b>com.java.main.dest.Address</class-b>
  <field>
     <a get-method="isIsPrimaryAddress">isIsPrimaryAddress</a>
     <b get-method="isIsPrimaryAddress">isIsPrimaryAddress</b>     
  </field>
</mapping>

If for Address object, the getter method is not defined as getFieldName, in that case you need to map as we have mapped isIsPrimaryAddress as shown above. All the other fields names have same names in both Address objects, and so the values will be copied automatically.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM