2

I have such a simple class structure which has abstract classes and subclasses. I want them to be mapped to destination class structure using ModelMapper.

I have checked and none of the solutions in other questions related to mapping abstract classes fixes my problem. This comment and this comment are somehow closest to what I want to achieve but in the scenario below it still fails.

The validation message I get from ModelMapper is:

org.modelmapper.MappingException: ModelMapper mapping errors:

1) Failed to instantiate instance of destination 
com.mls.services.MapperTest$DestParent. Ensure that 
com.mls.services.MapperTest$DestParent has a non-private no-argument 
constructor.
...

What is clear for me as DestParent class is abstract and cannot be instantiated.

Is there any way to make this working?

Here is a test source code as JUnit test case. Assertion in the bottom fails or validation throws an exception if I make some tries to fix this:

public class MapperTest {

  abstract static class SourceParent {}

  static class SourceSubA extends SourceParent {}

  static class SourceSubB extends SourceParent {}

  abstract static class DestParent {}

  static class DestSubA extends DestParent {}

  static class DestSubB extends DestParent {}

  static class Source {
    SourceParent item;

    public SourceParent getItem() {return item;}
    public void setItem(SourceParent item) {this.item = item;}
  }

  static class Dest {
    DestParent item;

    public DestParent getItem() {return item;}
    public void setItem(DestParent item) {this.item = item;}
  }

  @Test
  public void test() {
    ModelMapper modelMapper = new ModelMapper();

    TypeMap<Source, Dest> typeMap = modelMapper.createTypeMap(Source.class, Dest.class);

    // modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE);

    modelMapper
        .createTypeMap(SourceSubA.class, DestParent.class)
        .setConverter(
            mappingContext -> modelMapper.map(mappingContext.getSource(), DestSubA.class));

    modelMapper
        .createTypeMap(SourceSubB.class, DestParent.class)
        .setConverter(
            mappingContext -> modelMapper.map(mappingContext.getSource(), DestSubB.class));

    typeMap.addMapping(Source::getItem, Dest::setItem);

    TypeMap<SourceParent, DestParent> itemTypeMap =
        modelMapper.createTypeMap(SourceParent.class, DestParent.class);
    itemTypeMap.include(SourceSubA.class, DestSubA.class);
    itemTypeMap.include(SourceSubB.class, DestSubB.class);

    Source source = new Source();
    source.item = new SourceSubB();
    Dest dest = modelMapper.map(source, Dest.class);
    modelMapper.validate();

    Assert.assertTrue(dest.item instanceof DestSubB);
  }
}
zolv
  • 1,720
  • 2
  • 19
  • 36

0 Answers0