I'd like to combine MapStruct
mappers with Spring's Conversion model. So I declare every Mapper
interface as an extension of Spring's Converter
:
@Mapper public interface CarMapper extends Converter<Car, CarDto> { @Override CarDto convert(Car car); }
I can then use the mapper beans by injecting the standard ConversionService
:
class CarWarehouse { @Autowired private ConversionService conversionService; ... public CarDto getCarInformation(Car car) { return conversionService.convert(car, CarDto.class); } }
This works nicely, but I'm wondering whether there's a way to avoid injecting some Mappers into others directly via the uses
attribute. What I'd like to do is tell a Mapper to use
the ConversionService
for employing another mapper. However, since the ConversionService
's convert
method doesn't match MapStruct's standard pattern for a mapping method, the code generation plugin doesn't recognise that it can use the service when looking for a submapping. Basically, what I want to do is write
@Mapper(uses=ConversionService.class) public interface ParentMapper extends Converter<Parent, ParentDto>
instead of
@Mapper(uses={ChildMapper1.class, ChildMapper2.class, ChildMapper3.class}) public interface ParentMapper extends Converter<Parent, ParentDto>
Is there a way to achieve this?
Edit
Since it's been asked, let's say I've got a CarMapper
defined as above, with the types Car
and CarDto
having an attribute wheel
of type Wheel
and WheelDto
, respectively. Then I'd like to be able to define another Mapper like this:
@Mapper public interface WheelMapper extends Converter<Wheel, WheelDto> { @Override WheelDto convert(Wheel wheel); }
Right now, I'd have to add this Mapper explicitly:
@Mapper(uses = WheelMapper.class) public interface CarMapper extends Converter<Car, CarDto>
Which would then give the generated CarMapperImpl
an @Autowired
member of type WheelMapper
which would be called in order to map the attribute wheel
.
However, what I'd like is that the generated code would look somewhat like this:
@Component public class CarMapperImpl implements CarMapper { @Autowired private ConversionService conversionService; @Override public CarDto convert(Car car) { CarDto carDto = new CarDto(); carDto.setWheel(conversionService.convert(car.getWheel(), WheelDto.class); return carDto; } }
MapStruct is a code generator tool that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach. The generated mapping code uses plain method invocations and thus is fast, type-safe, and easy to understand.
MapStruct is an open-source Java-based code generator which creates code for mapping implementations. It uses annotation-processing to generate mapper class implementations during compilation and greatly reduces the amount of boilerplate code which would regularly be written by hand.
It's been more than a year since I asked this question, but now we've come up with an answer inside the MapStruct project itself - the MapStruct Spring Extensions project.
A CarMapper
example is provided as an example within the project.
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