Search code examples
javadozer

Dozer mapping inner classes


I need to map class A into class C using dozer framework.

public class A {

private String fielda1;
private String fielda2;

public String getFielda1() {
    return fielda1;
}
public void setFielda1(String fielda1) {
    this.fielda1 = fielda1;
}
public String getFielda2() {
    return fielda2;
}
public void setFielda2(String fielda2) {
    this.fielda2 = fielda2;
}
}


public class B {
private List<C> cList;

public List<C> getcList() {
    return cList;
}
public void setcList(List<C> cList) {
    this.cList = cList;
}

public static class C {
    private String fieldc1;
    private String fieldc2;

    public String getFieldc1() {
        return fieldc1;
    }
    public void setFieldc1(String fieldc1) {
        this.fieldc1 = fieldc1;
    }
    public String getFieldc2() {
        return fieldc2;
    }
    public void setFieldc2(String fieldc2) {
        this.fieldc2 = fieldc2;
    }
}
}

XML mapping file:

<mapping wildcard="false" map-null="false" map-id="test">
    <class-a>test.A</class-a>
    <class-b>test.B.C</class-b>
    <field>
        <a>fielda1</a>
        <b>fieldc1</b>
    </field>
    <field>
        <a>fielda1</a>
        <b>fieldc2</b>
    </field>
</mapping>

When i try to map these classes i got following exception:

org.dozer.MappingException: java.lang.ClassNotFoundException: test.B.C
at org.dozer.util.MappingUtils.throwMappingException(MappingUtils.java:88)
at org.dozer.util.DefaultClassLoader.loadClass(DefaultClassLoader.java:33)

It seams that dozer is not capable to handle this situation and uses class B as a package name. This issue can be resolved using custom converters. I just want to know is there any trick that could be used to convert these classes using just XML configuration ?


Solution

  • Try using test.B$C like in the following example:

    <mapping wildcard="false" map-null="false" map-id="test">
        <class-a>test.A</class-a>
        <class-b>test.B$C</class-b>
        <field>
            <a>fielda1</a>
            <b>fieldc1</b>
        </field>
        <field>
            <a>fielda2</a>
            <b>fieldc2</b>
        </field>
    </mapping>
    

    Also note that I changed the second field from fielda1 to fielda2, it appeared to be a typo in your example.

    Note: Because you set map-id="test" you must include mapId when you call map, like in:

    B.C destObject = mapper.map(a, B.C.class, "test");
    

    I tested and this is working correctly:

    A.java

    package com.test;
    
    public class A {
    
        private String fielda1;
        private String fielda2;
    
        public String getFielda1() {
            return fielda1;
        }
    
        public void setFielda1(String fielda1) {
            this.fielda1 = fielda1;
        }
    
        public String getFielda2() {
            return fielda2;
        }
    
        public void setFielda2(String fielda2) {
            this.fielda2 = fielda2;
        }
    }
    

    B.java

    package com.test;
    
    import java.util.List;
    
    public class B {
    
        private List<C> cList;
    
        public List<C> getcList() {
            return cList;
        }
    
        public void setcList(List<C> cList) {
            this.cList = cList;
        }
    
        public static class C {
    
            private String fieldc1;
            private String fieldc2;
    
            public String getFieldc1() {
                return fieldc1;
            }
    
            public void setFieldc1(String fieldc1) {
                this.fieldc1 = fieldc1;
            }
    
            public String getFieldc2() {
                return fieldc2;
            }
    
            public void setFieldc2(String fieldc2) {
                this.fieldc2 = fieldc2;
            }
        }
    }
    

    mapping.xml

    <?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">
    
        <mapping wildcard="false" map-null="false" map-id="test">
            <class-a>com.test.A</class-a>
            <class-b>com.test.B$C</class-b>
            <field>
                <a>fielda1</a>
                <b>fieldc1</b>
            </field>
            <field>
                <a>fielda1</a>
                <b>fieldc2</b>
            </field>
        </mapping>
    
    </mappings>
    

    Main.java

    package com.test;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.dozer.DozerBeanMapper;
    import org.dozer.Mapper;
    
    public class Main5 {
    
        public static void main(String[] args) throws Exception {
            List<String> mappingFiles = new ArrayList<String>(1);
            mappingFiles.add("mapping.xml");
    
            Mapper mapper = new DozerBeanMapper(mappingFiles);
    
            A a = new A();
            a.setFielda1("fielda1Value");
            a.setFielda2("fielda2Value");
    
            B.C destObject = mapper.map(a, B.C.class, "test");
    
            System.out.println(destObject.getFieldc1());
            System.out.println(destObject.getFieldc2());
        }
    
    }
    

    This outputs in the console:

    ...
    fielda1Value
    fielda1Value