ModelMapper - Failed to instantiate instance of destination

anat0lius picture anat0lius · Mar 2, 2017 · Viewed 12.2k times · Source

I'm working with mongodb so I'm decoupling entities from presentation layer creating DTOs (with hibernate-validator annotations).

public abstract class UserDTO {

    private String id;      
    @NotNull
    protected String firstName;
    @NotNull
    protected String lastName;
    protected UserType type;
    protected ContactInfoDTO contact;
    protected List<ResumeDTO> resumes;

    public UserDTO(){}
    //...

I'm trying to retrive from db this concrete class

public class UserType1DTO extends UserDTO {

    private CompanyDTO company;

    public UserType1DTO(){
        super();
    }

    public UserType1DTO(String firstName, String lastName, ContactInfoDTO contact, CompanyDTO company) {
        super(UserType.type1, firstName, lastName, contact);
        this.company = company;
    }
    /...

Like this:

return mapper.map((UserType1) entity,UserType1DTO.class);

And I get this error about not being able to instanciate ResumeDTO

Failed to instantiate instance of destination *.dto.ResumeDTO. Ensure that *.dto.ResumeDTO has a non-private no-argument constructor.

ResumeDTO is similar to UserDTO, is an abstract class and has concrete classes for each user type. All they have constructors with no arguments. What is the problem?

Answer

Pau picture Pau · Mar 2, 2017

You are trying to map a concrete class to an abstract class, this will not work. You can not use as destination an Abstract Class. Why? It can not be instantiated. So you must use a concrete class

Defintetively it wouldn't work a map with an Abstract Class destination:

mapper.map(entity, AbstractClass.class);
/*Error: java.lang.InstantiationException
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)*/

You must use a concrete class which extends the Abstract Class

public class ConcreteClass extends AbstractClass {
       //
}

And then map it to this concrete class:

mapper.map(entity, ConcreteClass.class);

More info:

Due to is not possible to insantiate an abstract class it will not work in desination properties neither.

There is an issue in Github related to this: https://github.com/jhalterman/modelmapper/issues/130