When using interfaces to define mapping and POJOs annotated with Lombok’s Builder, the signature for afterMapping needs to match the entry point of the mapper, with the additional parameter of the mapping target’s builder.
While working at a client, there was a somewhat complex task to map data from the legacy system to the greenfield system. The requirement was to update two target fields depending on another source field’s value. Being somewhat new to Mapstruct, but not search engines, I came across the @AfterMapping capability and I felt this was the way to go. The examples I found were not working for me because the afterMapping method was never called. That is, until I discovered the following solution:
Let’s say you have SourceClassA with some fields and a list of SourceClassB. Note that we use Lombok.
Here is our TargetClass:
The task is to map every SourceClassA and SourceClassB to one TargetClass (i.e. if an instance of SourceClassA has a list of 10 SourceClassBs, then there would be 10 TargetClasses). In addition to the standard mapping, we need to change the values of two fields on the target class if a field on the source class has a specific value. Just to make it more fun, we also need to map the target field D to the combination of field A and B from SourceClassB.
Given that, the mapper would look like so:
Notice that the method signature for afterMapping matches the entry point for mapping, with the addition of @MappingTarget TargetClass.TargetClassBuilder builder. Without this, the MapStruct will not be able to call the afterMapping method.
Here is a handy JUnit test for proof that fields A and B are changed when field B is greater than 10:
The example above is somewhat contrived and my code for the client was much nicer, but hopefully this will help in case of this complex mapping scenario!
Answers are just an email away. Drop us a line and the right person will get back to you as soon as possible.