I have the following class structure (code at the end):
abstract class AbstractThing
: I have some different kinds of things with common fieldsclass Foo extends AbstractThing
: a foo is one kind of thingabstract class AbstractReq <T extends AbstractThing>
: I have requests that relate to things, where the subject of the request is a field (T subject
)FooReq extends AbstractReq<Foo>
: Requests about foos, specificallyFooReqDto
: a DTO class with all of the fields in aFooReq
, flattened
I’m trying to map an instance of FooReq
to FooReqDto
using ModelMapper. If I don’t need to customize my type mappings, everything works great. But I do (in my actual code) need to customize some things, represented by the field called somethingDifferent
instead of subjectFooField
in FooReqDto
. Now when I run my test, I get the following error:
java.lang.ClassCastException: class com.example.test.TempTest$AbstractThing$ByteBuddy$PsTTXfw5 cannot be cast to class com.example.test.TempTest$Foo (com.example.test.TempTest$AbstractThing$ByteBuddy$PsTTXfw5 and com.example.test.TempTest$Foo are in unnamed module of loader ‘app’)
What am I missing when creating my type map? It doesn’t seem like there’s any inherent problem with mapping classes that have inheritance & generics involved, since it works when there’s no mapping. And the actual mappings I’m using worked fine before I pulled out the abstract classes (which is necessary to cut down on a lot of duplicate code).
Here’s the full code:
package com.example.test;
import org.junit.Test;
import org.modelmapper.ModelMapper;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class TempTest {
@Test
public void testStuff() {
final ModelMapper mapper = new ModelMapper();
mapper.createTypeMap(FooReq.class, FooReqDto.class)
.addMappings(map -> {
map.map(req -> req.getSubject().getFooField(), FooReqDto::setSomethingDifferent);
});
final FooReq req = new FooReq();
req.setSubmitted(true);
req.getSubject().setName("testFoo");
req.getSubject().setFooField("bar");
final FooReqDto dto = mapper.map(req, FooReqDto.class);
assertTrue(dto.isSubmitted());
assertEquals("testFoo", dto.getSubjectName());
assertEquals("bar", dto.getSomethingDifferent());
}
public static abstract class AbstractThing {
private String name;
// getters and setters omitted
}
public static class Foo extends AbstractThing {
private String fooField;
// getters and setters omitted
}
public static abstract class AbstractReq <T extends AbstractThing> {
protected T subject;
private boolean submitted;
// getters and setters omitted
}
public static class FooReq extends AbstractReq<Foo> {
public FooReq() {
super();
subject = new Foo();
}
}
public static class FooReqDto {
private boolean submitted;
private String subjectName;
private String somethingDifferent;
public FooReqDto() {
}
// getters and setters omitted
}
}