Modelmapper: Matches Multiple Source Property Hierarchies

Modelmapper: Matches Multiple Source Property Hierarchies

I cannot resolve modelMapper error. Do you have any ideas where is the issue?

NB: In view java.sql.Time doesn't have non-argument constructor I didn't find the better way than to write converter

org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) The destination property 
biz.models.CarWash.setSecondShift()/java.util.Date.setTime() matches 
multiple source property hierarchies:

biz.dto.CarWashDTO.getFirstShift()/java.time.LocalTime.getSecond()
biz.dto.CarWashDTO.getSecondShift()/java.time.LocalTime.getSecond()

The error was made by this code

@SpringBootTest
@RunWith(SpringRunner.class)
public class CarWashDTO2CarWash {

@Autowired
protected ModelMapper modelMapper;

@Test
public void testCarWashDTO2CarWash_allFiledShouldBeConverted(){
    CarWashDTO dto = CarWashDTO.builder()
            .name("SomeName")
            .address("SomeAddress")
            .boxCount(2)
            .firstShift(LocalTime.of(9, 0))
            .secondShift(LocalTime.of(20, 0))
            .phoneNumber("5700876")
            .build();

    modelMapper.addConverter((Converter<CarWashDTO, CarWash>) mappingContext -> {
        CarWashDTO source = mappingContext.getSource();
        CarWash destination = mappingContext.getDestination();
        destination.setId(source.getId());
        destination.setFirstShift(source.getFirstShift() == null ? null : Time.valueOf(source.getFirstShift()));
        destination.setSecondShift(source.getSecondShift() == null ? null : Time.valueOf(source.getSecondShift()));
        destination.setEnable(true);
        destination.setAddress(source.getAddress());
        destination.setBoxCount(source.getBoxCount());
        destination.setName(source.getName());
        destination.setDateOfCreation(source.getDateOfCreation());
        return destination;
    });

    final CarWash entity = modelMapper.map(dto, CarWash.class);
    assertNotNull(entity);
    assertEquals(2, entity.getBoxCount().intValue());
    assertEquals("SomeAddress", entity.getAddress());
    assertEquals("SomeName", entity.getName());
}

}

The modelmapper bean is built by the next configuration

@Bean
public ModelMapper modelMapper(){
    return new ModelMapper();
}

Dto:

public class CarWashDTO {
private Long id;
private String name;
private String address;
private String phoneNumber;
private Integer boxCount;
private LocalTime firstShift;
private LocalTime secondShift;
private LocalDateTime dateOfCreation;
}

Entity (firstShift and secondShift have java.sql.Time type):

public class CarWash {
private Long id;
private String name;
private String address;
private String phoneNumber;
private Integer boxCount;
private Time firstShift;
private Time secondShift;
private LocalDateTime dateOfCreation;
private Boolean enable;
private Owner owner;
}
0

5 Answers

try modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT)

3

This resolved my problem: modelMapper.getConfiguration().setAmbiguityIgnored(true);

3

You need to customize ModelMapper configuration during Bean initialization with the help of a PropertyMap:

@Bean
public ModelMapper modelMapper(){
    ModelMapper mm = new ModelMapper();

    PropertyMap<CarWashDTO, CarWash> propertyMap = new PropertyMap<CarWashDTO, CarWash> (){
        protected void configure() {
            map(source.getId()).setId(null);
        }
    }

    mm.addMappings(propertyMap);
    return mm;
}

I am not sure how it was with ModelMapper when question was asked but using converter should be straightforward. Instead of implementing a converter for the whole class implement it to the types that actually need conversion. So like:

public static Converter<LocalTime, Time> timeConverter = new AbstractConverter<>() {
    @Override
    protected Time convert(LocalTime source) {
        return null == source ? null : Time.valueOf(source);
    }
}; 

Then it is just to:

mm.addConverter(timeConverter);

Guess if using Spring or EJB you know howto add this into your configuration.

This resolved my problem:

modelMapper.getConfiguration().setAmbiguityIgnored(true);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Chloe Bennett
Author

Chloe Bennett

Chloe Bennett explores the intersection of pop culture, streaming entertainment, digital trends, and contemporary lifestyle. Her weekly commentary reaches thousands of culture enthusiasts.