3

I have the following classes:

public class MyEntity {
  private Set<MyOtherEntity> other;
}

public class MyDTO {
  private List<MyOtherDTO> other;
}

I created two PropertyMaps (using ModelMapper), one for each conversion from and to DTO

public class DTOToEntityPropertyMap extends PropertyMap<MyDTO, MyEntity> {
  @Override
  protected void configure() {
    List<MyOtherDTO> myOtherDTOs = source.getOther();
    Set<MyOtherEntity> myOtherEntities = new HashSet<>();
    for (MyOtherDTO myOtherDTO : myOtherDTOs) {
      MyOtherEntity myOtherEntity = ModelMapperConverterService.convert(myOtherDTO, MyOtherEntity.class);
      myOtherEntities.add(myOtherEntity);
    }
    map().setOther(myOtherEntities);
  }
}

public class EntityToDTOPropertyMap extends PropertyMap<MyEntity, MyDTO> {
  @Override
  protected void configure() {
    Set<MyOtherEntity> myOtherEntities = source.getOther();
    List<MyOtherDTO> myOtherDTOs = new ArrayList<>();
    for (MyOtherEntity myOtherEntity : myOtherEntities) {
      MyOtherDTO myOtherDTO = ModelMapperConverterService.convert(myOtherEntity, MyOtherDTO.class);
      myOtherDTOs.add(myOtherDTO);
    }
    map().setOther(myOtherDTOs);
  }
}

Adding the PropertyMaps to the ModelMapper creates the following error:

Caused by: org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Invalid source method java.util.List.add(). Ensure that method has zero parameters and does not return void.

I guess I cannot use List.add() in the configuration of a PropertyMap.

Then, what is the best way to implement the conversion of a List to a Set and backwards in the ModelMapper?

Stefanos Kargas
  • 10,547
  • 22
  • 76
  • 101

1 Answers1

4

The PropertyMap must use it to map properties. If you put something of different logic it will throw an exception.

So, you have the next options (I put the examples in one direction, the other is the same):

Option 1: Ensure PropertyMap match the properties

Using a property map and ensure ModelMapper will use it, take a look the rules of Matching Strategies:

  • Standard: by default.
  • Loose
  • Strict

Use the one which ensure your property list other will match with the destination property other. For example, if you use Strict Strategy and is not in the correct order it will not match it.

Then, if you are sure the property will match ModelMapper will map the property following its rules for you or if you need it, you would be able to create a PropertyMap whith source MyOtherEntity and destination MyOtherDTO and add it to your ModelMapper instance.

public class DTOToEntityPropertyMap extends PropertyMap<MyOtherEntity, MyOtherDTO> {
  @Override
  protected void configure() {
    map().setPropertyOfOther(source.getPropertyOfOther());
    //and so on...
  }
}

modelMapper.addMappings(new DTOToEntityPropertyMap());

Note: if your parent mapping (In your case MyEntity to MyDto) have other PropertyMap you would need to add the PropertyMapping of the list classes before the parent, if not it will not use this property map.

Option 2: Create a converter of the lists and use it

Other option is to create a Converter of the classes of your lists (MyOtherEntity -> MyOtherDto) and use it in the parent PropertyMap.

Converter<Set<MyOtherEntity> , List<MyOtherDto>> toOtherDto = new Converter<Set<MyOtherEntity> , List<MyOtherDto>>() {
  public String convert(MappingContext<Set<MyOtherEntity> , List<MyOtherDto>> context) {
    Set<MyOtherEntity> source = context.getSource();
    List<MyOtherDto> destination = context.getDestination();
    //Convert it using the logic you want (by hand for example)

    return destination;
  }
};

Then you must use it in your Parent PropertyMap, as next:

public class EntityToDTOPropertyMap extends PropertyMap<MyEntity, MyDTO> {

  Converter<Set<MyOtherEntity> , List<MyOtherDto>> toOtherDto = new Converter<Set<MyOtherEntity> , List<MyOtherDto>>() {
    public String convert(MappingContext<Set<MyOtherEntity> , List<MyOtherDto>> context) {
      Set<MyOtherEntity> source = context.getSource();
      List<MyOtherDto> destination = context.getDestination();
      //Convert it using the logic you want (by hand for example)

      return destination;
    }
  };

  @Override
  protected void configure() {
    using(toOtherDto).map(source.getOther()).setOther(null);
  }
}

Then ensure this PropertyMap is added to your ModelMapper instance:

modelMapper.addMappings(new EntityToDTOPropertyMap());
Stefanos Kargas
  • 10,547
  • 22
  • 76
  • 101
Pau
  • 14,917
  • 14
  • 67
  • 94