Using Lombok & Mapstruct to write mapping services instantly

This tutorial introduces how to use Lombok & Mapstruct libraries together, in order to create getters & setters methods, then generating mapping services between DTO(s) and Entities.

Demo repository: https://github.com/sunhong87/user-vehicles-app

Lombok

There are tons of articles that introduce about this library, the major benefit is helping developers to generating common methods during compile time, such as getters & setters, constructors, etc.

Therefore, it can reduce duplicated code when some classes have same attributes’ name, it also can help developers to prevent too many arguments constructors issue.

Behind the scene, Lombok library will generate those methods, constructors during compile time. Example:

Using @Getter, @Setter annotation to generate getter, setter methods
A Model with Lombok getter & setter annotations
Lombok generates class
Real generated class

Mapstruct

MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach.
https://mapstruct.org/

There are tons of libraries having same feature, but Mapstruct is one of libraries having good performance, because it doesn’t use Java Reflection to do the “magic”, it actually generate real implementation classes.

https://www.baeldung.com/java-performance-mapping-frameworks

For mapped bean attributes it is assumed by default that the attribute has the same name in the source bean.

Example:

A Mapping interface with annotation
Mapping service interface
  • @Mapper : Marks an interface or abstract class as a mapper and activates the generation of a implementation of that type via MapStruct.
  • componentModel="spring" : Mark the generation should be declared @Component as Spring bean.
  • uses: Other mapper types used by this mapper. If componentModel="spring" is used, declared classes should be able to be injected by Spring container (mark @Component, @Service ).
  • @Mapping : Configure the way of mapping on specific attribute.
  • source : A source attribute should be mapped from.
  • target : A target attribute should be mapped to.
  • qualifiedByName : Name of method should be used to map between source and target . The method must be declared with @Name .
  • ignore=true : Ignore mapping on specific attribute.
  • expression(“java(…)”) : java code should be used to map on specific attribute.

Behind the scene, Mapstruct will generate real implementation classes, base on the mapping services interfaces and annotations.
By default, the implementations will be generated undertarget/generated-sources/annotations/<packagesName>

Configure Lombok, Maptruct with Maven

  1. Add dependencies:
  • If parent project is spring-boot-starter-parent , Lombok version is already defined in parent pom.
  • If you don’t configure parent project with spring-boot-starter-parent , you must define a specific version.
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>

2. Configure with maven-compile-plugin : To generate implementations with maven command.

Lombok must be declared before Mapstruct, in order to let Lombok generate implementations before Mapstruct does.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>

Generate implementations and running in IDE

This example is written in Eclipse. Others IDE may configured same.

  1. Execute command mvn clean compile or test or install to generate the implementations. The implementations are located under:

2. Running tests or application in IDE
- In order to let application know the generated implementations during running tests or applications. You must add generated folder as link source in IDE.

Right the project -> Build Path -> Configure Build Path -> Source -> Link Source -> Browse -> Locate the path target/generated-sources/annotations under current project -> Finish

Bonus

Constructor injection

Using constructors to inject beans is a good practice, however, if there are too many beans which are required, the constructor may have too many arguments, it will trigger too many argument error.
By using Lombok, you can skip this issue during implementation. For example:

A service uses constructor injection with Lombok
  • @RequiredArgsConstructor : A Lombok annotation to active constructor generation with @NonNull class attributes.
  • @NonNull : Using with @RequiredArgsConstructor to mark this attribute should be used as constructor argument.

There is also @AllArgsConstructora annotation to active constructor generation with all class attributes.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store