11.2. Reducing Boilerplate Code (Lombok)¶
11.2.1. Lombok¶
Lombok is a library used for reducing the boilerplate code from Java source code.
Boilerplate code is a typical source code that cannot be omitted by language specification. Basically Boilerplate code does not have a specific logic hence it becomes redundant code in implementation.
Following are the typical Boilerplate source code in Java language.
- getter / setter methods for accessing the member variables
equals
/hashCode
methodstoString
methods- Constructors
- Closing process of resources (input and output stream, etc.)
- Generation of logger instance
In Lombok, boilerplate code gets generated at the time of compilation thereby providing a mechanism to remove redundant code from the source code developed by the developer.
Tip
For removing the Boilerplate code, the language specification for closing the resources (input and output stream, etc.) are improved by newly added [try-with-resources] statement in Java SE7.
Java language itself is improving in every version-up for removing the redundant code. Lambda support in Java SE8 is also called as typical language specification improvement.
11.2.2. Efficiency of Lombok¶
Below, JavaBean source code is created using Lombok.
package com.example.domain.model;
@lombok.Data
public class User {
private String userId;
private String password;
}
In Lombok, required methods for JavaBean gets created by only assigning @lombok.Data
annotation at class level.
By only assigning @Data
annotation of Lombok, it is possible to obtain the same effect
as classes generated by (the source code output using the auto-generation function of Eclipse) which has about 60 lines of code given below instead of 10 lines of code.
package com.example.domain.model;
public class User {
private String userId;
private String password;
public User() {
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((password == null) ? 0 : password.hashCode());
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (userId == null) {
if (other.userId != null)
return false;
} else if (!userId.equals(other.userId))
return false;
return true;
}
@Override
public String toString() {
return "User [userId=" + userId + ", password=" + password + "]";
}
}
11.2.3. Lombok setup¶
11.2.3.1. Inclusion of dependent library¶
In order to use a class that is offered by Lombok, add Lombok as dependency library.
<!-- (1) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope> <!-- (2) -->
</dependency>
Sr.No | Description |
---|---|
(1)
|
Add Lombok dependent library in the Lombok targeted project’s pom.xml . |
(2)
|
Since Lombok library is not required at the time of application execution, appropriate scope is provided . |
Note
Since it is assumed to manage the dependent library version with the parent project terasoluna-gfw-parent the above dependency library used by terasoluna-gfw-parent is defined by Spring IO Platform.
11.2.3.2. IDE Integration¶
If you want to use Lombok on IDE, it is necessary to install the Lombok to IDE in order to work with compile (build) function provided by the IDE.
In this guideline, introduced how to install Lombok to Spring Tool Suite (Later referred as the “STS”). However installation methods are different depending on IDE henceforth refer this page in case you want to use IDE besides STS.
11.2.3.2.1. Download Lombok¶
Download the jar file of Lombok.
The jar file of Lombok,
- Download page of Lombok
- Local repository of Maven can retrieve from (Normally,
$HOME/.m2/repository/org/projectlombok/lombok/<version>/lombok-<version>.jar
)
11.2.3.2.2. Lombok Installation¶
Launch the installer by running (double-click) the downloaded Lombok jar file.
After selecting the targeted STS, follow installation process by pressing the “Install / Update” button. The installer will automatically detect the location of supported IDE However if cannot auto detected, it is necessary to specify the IDE by pressing the “Specify location …”
Once Lombok installation completes, it is possible to start development using Lombok on STS after booting (Or re-booting) STS.
11.2.4. How to use Lombok¶
From here, the specific use of Lombok is described.
If Lombok is used first time, it is recommendation to watch Lombok [Demo Video]. The length of Demo Video is less than 4 minutes and described the most basic usage.
11.2.4.1. Lombok Annotations¶
Typical annotations provided by Lombok are introduced below.
For Detailed usage of each annotation as well as annotation that have not been explained in this guideline,
please refer,
Sr.No | Annotation | Description |
---|---|---|
@lombok.Getter | Annotation for generating getter method. If annotation is specified at class level, it is possible to generate getter methods for all respective fields. |
|
@lombok.Setter | Annotation for generating setter method. If annotation is specified at class level, it is possible to generate setter methods for all non-final respective fields. |
|
@lombok.ToString | Annotation for generating toString method. |
|
@lombok.EqualsAndHashCode | Annotation for generating equals and hashCode method. |
|
@lombok.RequiredArgsConstructor | Annotation for generating constructor with the required arguments for those fields (final field etc) where initialization required. If all fields are optional fields, the default constructor (without argument constructor) is generated. |
|
@lombok.AllArgsConstructor | Annotation for generating constructor having all fields in arguments. | |
@lombok.NoArgsConstructor | Annotation for generating default constructor. | |
@lombok.Data | Short cut annotation for If |
|
@lombok.extern.slf4j.Slf4j | Annotation for generating logger instance of SLF4J. |
11.2.4.2. Creation of JavaBean¶
If an application is built the way that this guideline is recommended,
- Form class
- Resource class(REST API configured)
- Entity class
- DTO class
it is necessary to create a JavaBean for above classes.
Below is the example of creating a JavaBean.
package com.example.domain.model;
import lombok.Data;
@Data // (1)
public class User {
private String userId;
private String password;
}
Sr.No | Description |
---|---|
(1)
|
By assigning a
are created. |
11.2.4.2.1. How to exclude specific field from toString¶
At the time of converting the state of object into a string,
- Field that holds an object of cross reference relationship
- Field that holds sensitive information such as personal information and password
etc are required to exclude from the scope of string conversion. If these fields are not excluded from the string conversion,
- The
StackOverflowError
andOutOfMemoryError
occurs due to circular reference - There is a possibility of leakage the personal information due to use of converted string
Henceforth it is necessary to take an attention.
Warning
If @Data
or @ToString
annotation is used at the Entity class of JPA,
it is necessary to keep in mind that it tends to the circular reference.
How to exclude a specific field from string conversions are indicated below.
package com.example.domain.model;
import lombok.Data;
import lombok.ToString;
@Data
@ToString(exclude = "password") // (1)
public class User {
private String userId;
private String password;
}
Sr.No | Description |
---|---|
(1)
|
Specify the If you call
is converted to the string. |
11.2.4.2.2. How to exclude specific field from equals and hashCode¶
If equals
method and hashCode
method generated using Lombok annotation,
field that holds an object of cross reference relationship needs to be removed.
If methods are generated without excluding these fields,
the StackOverflowError
and OutOfMemoryError
occurs due to circular reference
henceforth it is necessary to take an attention.
Warning
If @Data
annotation, @Value
annotation, @EqualsAndHash
annotation is used at the Entity class of JPA,
it is necessary to keep in mind that it tends to the circular reference.
How to exclude a specific field is indicated below.
package com.example.domain.model;
import java.util.List;
import lombok.Data;
@Data
public class Order {
private String orderId;
private List<OrderLine> orderLines;
}
package com.example.domain.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@ToString(exclude = "order")
@EqualsAndHashCode(exclude = "order") // (1)
public class OrderLine {
private Order order;
private String itemCode;
private int quantity;
}
Sr.No | Description |
---|---|
(1)
|
Specify the @EqualsAndHashCode annotation to the class level and list the name of fields that you want to exclude into exclude attribute. |
Tip
Instead of specifying the field to be excluded, it is also possible to specify to use only specific fields.
@Data @ToString(exclude = "order") @EqualsAndHashCode(of = "itemCode") // (2) public class OrderLine { private final Order order; private final String itemCode; private final int quantity; }
Sr.No Description (2)In case of using only specific fields, specify the name of fields that you want to include into
of
attribute of@EqualsAndHashCode
annotation.In the above example,
equals
method andhashCode
method get generated by referring onlyitemCode
field.
11.2.4.2.3. How to generate constructor for field initialization¶
If you want to create an instance of JavaBean from the implementation code of application, it is more convenient that having constructor where initial value of the field can be passed as an argument, to eliminate the redundant code.
If you create an instance using the default constructor, the code would be like below.
public void login(String userId, String password) {
User user = new User();
user.setUserId(userId);
user.setPassword(password);
// ...
}
How to generate a constructor that specifies the initial values of the field are indicated below.
package com.example.domain.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor // (1)
@NoArgsConstructor // (2)
@ToString(exclude = "password")
public class User {
private String userId;
private String password;
}
public void login(String userId, String password) {
User user = new User(userId, password); // (3)
// ...
}
Sr.No | Description |
---|---|
(1)
|
Specify the @AllArgsConstructor annotation to the class level, to generate a constructor that takes the initial values of all fields as an argument. |
(2)
|
Specify the It is necessary to generate a default constructor if going to be used as JavaBean. |
(3)
|
Create an instance of JavaBean by calling the constructor that having initial values of the field. If default constructor is used, instance can be generated in one step instead of 3 steps. |
Tip
If you want to create above User
class as Immutable class instead of JavaBean,
it is preferable to use @lombok.Value
annotation.
Please refer Lombok reference for @Value
annotation.
11.2.4.3. Creating logger instance¶
If it is necessary to generate a logger instance for output a debug log and application log, it is preferable to use annotations for creating a logger instance.
If you want to create a logger instance without using Lombok annotations, below could be code.
package com.example.domain.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class AuthenticationService {
private static final Logger log = LoggerFactory.getLogger(AuthenticationService.class);
public void login(String userId, String password) {
log.info("{} had tried login.", userId);
// ...
}
}
How to create a logger instance using Lombok annotation is described below.
package com.example.domain.service;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
@Slf4j // (1)
@Service
public class AuthenticationService {
public void login(String userId, String password) {
log.info("{} had tried login.", userId); // (2)
// ...
}
}
Sr.No | Description |
---|---|
(1)
|
Generate SLF4J logger instance by specifying In this guideline, it is prerequisite to output a log using By default, FQCN class that granted the annotation (In above example |
(2)
|
Output the log by calling the method of SLF4J logger instance that has been generated by Lombok. In above example,
will be output. |
Tip
If you want to change the logger name that is used by default,
specify optional logger name in the topic
attribute of @Slf4j
annotation.