MapStruct — Let me write the tedious piece of code for you!

Akshay Jain
Globant
Published in
6 min readJun 3, 2021
Photo by J. Kelly Brito on Unsplash

Are you still breaking rock by writing boilerplate code for bean mapping in your multi-layered architectural application?

If so, the following 10 minutes will bring joy to your coding style.

Introduction

Let me introduce MapStruct — A powerful Java annotation processor to ease our lives by writing type-safe bean mapping classes for us.

Compared to writing mapping code by hand, MapStruct saves time by generating the code which is tedious and error-prone to write manually at compile time. It uses sensible defaults but steps out of our way when it comes to configuring or implementing special behavior as per our business requirement.

You must be thinking how this magic works, so without any further ado, let’s get started with Mapstruct.

Set-up

Dependencies -

  1. In case you use Maven, add the following dependencies to your POM.xml

Configure with maven-compile-plugin to generate implementations with maven command.

Tip — If also using Lombok, declare path definition of Lombok before Mapstruct to let the Lombok generate implementations before Mapstruct does, so that Mapstruct can use Lombok generated methods.

2. In case you use Gradle, add the following dependencies to your build.gradle

3. If using an IDE, do not forget to perform following actions -

a) Enable Annotations Processors( Preference/Settings->Build Execute Deployment ->Compiler->Annotations Processors )

b) Install MapStruct plugin to your IDE -

  • To install MapStruct plugin in Eclipse, click me
  • To install MapStruct plugin in IntelliJ, click me

Implementation

For this magic to happen we just need to create an Interface, annotated with @Mapper annotation of MapStruct with some methods declaration.

Let’s take an example:

Suppose we have two POJO classes — Customer.java and CustomerDto.java and we want to perform field mappings between them.

Customer.java

CustomerDto.java

To establish a mapping logic between above two POJOs we just need to write an interface as below -

CustomerMapper.java

@Mapper — This annotation will tell MapStruct to generate the implementation class for the interface.

MapStruct will infer the intention of the user by looking into the return type and parameter type of the declared methods and will implement logic for it.

After Compiling the above code, you will get the below auto-generated class by the MapStruct -

CustomerMapperImpl.java

Here we can see that MapStruct has generated the implementation class for our Mapper interface by following all the Java best practices. This is a case just for two fields in the POJO, but consider the real life scenario where we can have a large no. of fields and POJOs, in that case Mapstruct comes very handy to generate mappings for us.

This is so cool, right! 😎

We can find the generated classes under following location:

  • If using maven - target > generated-sources > annotations
  • If using gradle - build > generated > annotationProcessor

The above scenario has been just a basic one where field names were identical, but I know life is not so easy, so now let’s dirty our hands with some real life scenarios one by one :

• Mapping Fields With Different Field Names:

The new POJOs will be -

To map these fields with different names, all we have to do is just tell MapStruct which field maps to which. With a very simple annotation @Mapping, the new Mapper Interface will look as shown below -

Bonus Point -

What happens when someone changes the field name in one of the POJOs but forgets to update the same in the Mapper Interface???

Will it give a compile time error???

The answer is a big NO, but it can show some undesired behaviour at runtime as the mapping won’t be performed for that field.

To catch this mistake in compile time, we can configure our Mapper as below -

Note: Use this configuration only if you are sure that you want to map all the fields present in a POJO, else you can keep ReportingPolicy as IGNORE or WARN to not get compilation error.

• Mapping Beans With Nested Beans:

Suppose we have Order.java and OrderDto.java within Customer.java and CustomerDto.java respectively as below -

To get mappings for the nested beans, all we have to do is add methods for Order.java to OrderDto.java and vice versa, if MapStruct detects that the object type needs to be converted and the method to convert exists in the same class, it will use it automatically.

Our new Mapper Interface will look like -

• Mapping Fields Which Are Inside Nested Bean:

Let’s consider we want to map id from Order.java which is a nested bean of Customer.java to orderId in CustomerDto.java.

The mapper will look like below -

Similarly, we can map selected fields from one nested bean to another nested bean -

• Mapping Methods With Several Source Parameters:

MapStruct also supports mapping methods with several source parameters. This is useful in order to combine several entities into one data transfer object.

The following shows an example, where we have two input POJOs Customer.java and Order.java are getting mapped to single POJO CustomerDetailDto.java:

Conclusion

This was a basic introduction to Mapstruct, you can always club MapStruct with Lombok to speed up your development and make your code error and maintenance free.

If you are aware about other mapping frameworks like Dozer, Orika, ModelMapper and JMapper, you must be thinking why should I choose MapStruct? What is so special about it?

So let me tell you, you are thinking in the right direction and the one-line answer for that is -

MapStruct gives us the best performance with the least configuration.

For further performance analysis of all the Mapping Frameworks, go through the information rich article from Baeldung.

For the advanced concepts of Mapstruct like Spring Integration, Type Conversion, Collection Mapping and many more, please browse through the next blog of this series, click me, I’ll get you there!

Happy Coding!

--

--

Akshay Jain
Globant
Writer for

A Technology Geek by passion and Software Developer by profession who loves to capture nature’s beauty through his lens and explore the unexplored in free time.