Search code examples
javaconstructordozerprivate-constructor

Private constructor not affecting Dozer


Just for understanding Dozer, I created two classes PrimaryType and SecondaryType and tried to map them using Dozer. Dozer was seamlessly able to map them.

Tried making the constructor of the SecondaryType to private but still Dozer was successfully able to create an object of type SecondaryType and was able to map its fields. Can anyone explain how is it possible for Dozer instantiate a class which has private constructor?

PrimaryType.java

package in.yogi;

public class PrimaryType
{
    private String name;
    private int age;

    public PrimaryType(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "PrimaryType [name=" + name + ", age=" + age + "]";
    }

}

SecondaryType.java

package in.yogi;

public class SecondaryType
{
    private String name;
    private int age;
    private SecondaryType() {

    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "SecondaryType [name=" + name + ", age=" + age + "]";
    }
}

AppMain.java

package in.yogi;

import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;

import in.yogi.PrimaryType;

public class AppMain {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("This is the main Application!!!");
        PrimaryType sourceObject = new PrimaryType("Munsamy", 20);
        System.out.println(sourceObject);
        Mapper mapper = new DozerBeanMapper();
        SecondaryType destObject =  
            mapper.map(sourceObject, SecondaryType.class);
        System.out.println(destObject);
    }
}

Output:

PrimaryType [name=Munsamy, age=20]
log4j:WARN No appenders could be found for logger (org.dozer.config.GlobalSettings).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
SecondaryType [name=Munsamy, age=20]

Solution

  • This is usually done with reflection. The Dozer documentation explains:

    The bean mapper is written in Java and relies heavily on the Jakarta Commons Bean Utils package for Java Bean utility methods.

    Reading the docs of the Commons Beanutils project, you can find the needed explanation:

    The Java language provides Reflection and Introspection APIs (see the java.lang.reflect and java.beans packages in the JDK Javadocs). However, these APIs can be quite complex to understand and utilize. The BeanUtils component provides easy-to-use wrappers around these capabilities.

    You can easily do it yourself:

    public static void main(String[] args) throws Exception {
        Constructor<SecondaryType> constructor = SecondaryType.class.getDeclaredConstructor();
        constructor.setAccessible(true); // if not set accessible, you will get an exception
        SecondaryType instance = constructor.newInstance();
        System.out.println(instance);
    }