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:
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:
@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. IfcomponentModel="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 betweensource
andtarget
. 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
- 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.
- Execute command
mvn clean compile
ortest
orinstall
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.
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:
@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 @AllArgsConstructor
a annotation to active constructor generation with all class attributes.