Search code examples
javamavenmodelmappergenerics

ModelMapper changes generic type on runtime - weird behavior


I am facing a very strange behavior in Java. I got two different classes that has no hierarchical connection: Class Template (Type hierarchy is Object -> A -> B -> Template), and class TemplateDto (Object -> TemplateDto).

I am using ModelMapper (org.modelmapper.ModelMapper) for mapping between the two classes (which uses the default mapping since the field names are identical).

There is the following code:

List<Template> templates = cvService.getTemplates();
List<TemplateDto> resultDtos = new ArrayList<TemplateDto>();
modelMapper.map(templates,resultDtos);
TemplateDto example = resultDtos.get(0);

And the last line throws:

java.lang.ClassCastException: com.vs.framework.domain.cv.Template cannot be cast to com.vs.framework.dto.cv.TemplateDto

This is very weird. When i am debugging this section i see that after the mapping, resultDtos is a list of type List instead of List which blows my mind.

I have tried to clean my tomcat, maven clean install but it still happens.

Any ideas?


Solution

  • Java implements generics with type erasure, meaning that the runtime code has no way of knowing that your ArrayList is supposed to be an ArrayList<TemplateDto>.

    http://modelmapper.org/user-manual/generics/ describes how to use a TypeToken to get around this problem with lists. It should look something like this:

    List<Template> templates = cvService.getTemplates();
    Type listType = new TypeToken<List<TemplateDto>>() {}.getType();
    
    List<TemplateDto> resultDtos = modelMapper.map(templates, listType);
    TemplateDto example = resultDtos.get(0);