Reducing Boilerplate code in Java Application
Project Lombok and MapStruct
One of the most criticized things about JAVA is how verbose it is. This is especially true about some simple POJO classes that are only used to store some data or for transferring data from one layer of your application to another layer.
You need getter, setters, constructors, toString implementation and mapper classes to map an entity to DTO objects. Wikipedia describes boilerplate code as - "In computer programming, boilerplate code or just boilerplate are sections of code that are repeated in multiple places with little to no variation".
This wouldn’t seem like a tedious task for a small application where you might have only a couple of classes but in a real-world application you might end up writing a bunch of repetitive code which might be avoided by using code generation libraries.
What can be done?
In this post, I will discuss two different ways to reduce boilerplate code -
- Project Lombok
- MapStruct
Project Lombok
It's a Java library that helps in reducing boilerplate code like getter, setters, constructors. The injected code is immediately available for use in your application.
Setup
To set up Lombok in your application, you will have to add lombok.jar in your application classpath. And if you are using maven you will have to just add following dependency in your pom.xml -
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
You will also need to add Lombok to your IDE. If you use eclipse or STS you can set it up by double-clicking Lombok.jar and following a simple installation wizard.
Getting Started
To generate different methods like getter, setters constructors and others you will have to annotate your POJO class with @Data annotation. It will generate getter, setters, default constructor. equals, hashCode. and toString method as shown in this picture:-
@Data annotation is a shortcut for many other Lombok annotations. Sometimes it adds too much unnecessary code which we don't need. In those scenarios, we can use specific annotations. Some of the most commonly used annotations are
@Getter generates only Getter methods @Setter generates only setter methods @AllArgsConstructor generates a constructor with one parameter for all fields in the class.
@ToString generates the toString method @EqualsAndHashCode generates equals and hashCode method
MapStruct
MapStruct is a code generator that helps in the implementation of mapping between Java bean types. The generated mapping code uses plain method invocations and thus is fast, type-safe and easy to understand.
Setup
If you are using Maven to build your application add the following to your pom.xml
<properties>
<org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
Getting Started
Let's assume we have a class Employee and its corresponding data transfer object (DTO). Both the class are similar, only the employee name attributes have different names.
Employee.java
EmployeeDTO.java
To generate a mapper for creating an EmployeeDto object from the Employee object, a mapper interface needs to be defined.
EmployeeMapper.java
The @Mapper annotation marks the interface as a mapping interface and lets the MapStruct processor kick in during compilation. The actual mapping method expects the source object as a parameter and returns the target object. Its name can be freely chosen.
MapStruct automatically maps the attributes having the same name, but in scenarios, if we have different names for the attributes then we can map the attributes using @Mapping annotation as shown above.
Based on the mapper interface, clients can perform object mappings in a very easy and type-safe manner:
Conclusion
Java is a verbose language, and adding boilerplate code makes coding in Java time-consuming. To overcome this issue, Lombok and MapStruct are great libraries to help us reduce the boilerplate code.
You can find the example source code @ Github .