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;
}
Model Mapper The main role of ModelMapper is to map objects by determining how one object model is mapped to another called a Data Transformation Object (DTO).
The first is by adding the converter to a ModelMapper: modelMapper. addConverter(personConverter); This, in turn, sets the converter against the TypeMap corresponding to the source and destination types Person and PersonDTO .
ModelMapper Introduction To avoid having to write cumbersome/boilerplate code to map DTOs into entities and vice-versa, we are going to use a library called ModelMapper. The goal of ModelMapper is to make object mapping easy by automatically determining how one object model maps to another.
Property Mapping. For most object models, ModelMapper does a good job of intelligently mapping source and destination properties. But for certain models where property and class names are very dissimilar, a PropertyMap can be created to define explicit mappings between source and destination properties.
The destination property com..BaseEntity.setId () matches multiple source property hierarchies......... The version of org.modelmapper that I am using is: 2.0.0
In this tutorial, we explained how lists are mapped by manipulating generic types in ModelMapper. We can make use of TypeToken, generic type mapping, and property mapping to create object list types and make complex mappings. The complete source code for this article is available over on GitHub.
By doing so, ModelMapper can compare private fields in the mapping classes (objects). In this configuration, it's not strictly necessary that all fields with the same names exist in both classes. Several Matching Strategies are allowed.
try modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT)
This resolved my problem:
modelMapper.getConfiguration().setAmbiguityIgnored(true);
You need to customize ModelMapper configuration during Bean initialization with the help of a PropertyMap: http://modelmapper.org/user-manual/property-mapping/
@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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With