Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ModelMapper with Spring, where to put explicit mappings?

I'm using ModelMapper with Spring. In my controller class I'm autowiring the ModelMapper bean:

@Autowired
private ModelMapper mapper;

I want to do an explicit mapping between my model class and my DTO in my controller methods, something like:

modelMapper.addMappings(mapper -> {
  mapper.map(src -> src.getBillingAddress().getStreet(),
      Destination::setBillingStreet);
  mapper.map(src -> src.getBillingAddress().getCity(),
      Destination::setBillingCity);
});

And then use the mapper to map the classes.

My question is, is it right to add explicit mappings in every controller method call? Will object modelMapper start to grow in memory size?

Other solution is to add the mapping only one time when ModelMapper bean is created, but I don't think that putting mapping logic in a bean configuration is a good decision.

like image 423
italktothewind Avatar asked Sep 23 '18 01:09

italktothewind


People also ask

How do I use TypeMap in ModelMapper?

You can define a property mapping by using method references to match a source getter and destination setter. typeMap. addMapping(Source::getFirstName, Destination::setName); The source and destination types do not need to match.

How does ModelMapper work in spring boot?

ModelMapper consists of two separate processes: the matching process, where a source and destination type's properties are matched to each other, and the mapping process where matched property values are converted from a source to destination object.

Can we Autowire ModelMapper?

When we use the starter, we just add a Gradle dependency and then autowire the ModelMapper instance in our controllers. @Controller public class TaskController { @Autowired private TaskRepository taskRepository; @Autowired private ModelMapper modelMapper; ... }


1 Answers

It is totally fine to setup the mapping logic in the bean configuration of ModelMapper. Mapping is the actual task of that class, so it should be configured when it is created.

Nevertheless, I prefer to create multiple dedicated mapper definitions, one for each type or group of related types.

Doing it this way keeps the configuration aspect separate from the actual usage of the mapper in the controllers - without creating a big pile of unrelated mapping configuration code in one class. Indeed, configuring the mapper in each controller would violate principles like DRY (don't repeat yourself) and SoC (separation of concerns).

In your case (singleton ModelMapper) you may create @Configuration-annotated classes for each type or group of types you want to map. Within that class you would receive the ModelMapper and add the type mappings. Add your configuration code to either

  • a ModelMapper-receiving constructor or
  • a @PostConstruct-annotated method which accesses an @Autowired ModelMapper attribute.

I haven't used ModelMapper myself yet but after peeking into its codebase I would guess that if you follow your original approach, the memory usage would not increase but you would find exceptions about duplicate mappings getting thrown.

like image 86
Hero Wanders Avatar answered Sep 18 '22 08:09

Hero Wanders