Using Project Lombok with Gradle
0 CommentsIntroduction
In this post, we are going to write about Project Lombok, a must-have tool for every Spring programmer.
Lombok is a Java library, that enhances programmer productivity, by providing several helpful annotations. It makes classes shorter and frees programmers from writing much boilerplate code.
After reading this tutorial, we will be able to setup Lombok with Gradle for your Spring Boot project.
Setup
For this tutorial, we will be using Gradle to setup Lombok dependency.
Gradle-lombok plugin
A preferable way to setup Lombok in Gradle is by using a gradle-lombok plugin. This is done by using Gradle plugins DSL:
plugins { id 'org.springframework.boot' version '2.1.7.RELEASE' id 'java' id 'io.freefair.lombok' version '3.8.4' }
If we are working with an older Gradle version, which uses legacy plugin application, we can use code below:
buildscript { repositories { maven { url 'https://plugins.gradle.org/m2/' } } dependencies { classpath 'io.freefair.gradle:lombok-plugin:3.8.4' } } apply plugin: "io.freefair.lombok"
Without a plugin
If for any reason we don’t want to use a plugin, we can use these standard dependencies:
compileOnly 'org.projectlombok:lombok:1.18.8' annotationProcessor 'org.projectlombok:lombok:1.18.8'
There are several more ways to install Lombok, you can find them on the official project site – https://projectlombok.org/.
Note: In this tutorial, we are using IntelliJ IDEA as our IDE. For Lombok to work, we need to turn on annotations processing. To do that, go to File -> Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors and mark “Enable annotation processing”.
Code
Let’s see Lombok in action!
Our sample code will consist of two DTO (Data Transfer Object) classes, that will have Lombok annotations:
- Person – DTO class, describes a person
- Job – DTO class, describes person job
Additionally, we will test our DTOs in the main application method.
Job
Job class is a simple DTO that contains only three fields – job
, position
, salary
.
This class will be annotated class with Lombok’s @Data
.
import lombok.Data; @Data public class Job { private final String job; private String position; private double salary; }
We will see the real value of this class annotation during tests, but a small explanation is necessary.
Our @Data
annotation above the Job
class added several things for us, It is really just syntactic sugar, that groups several more annotations, that are often used on DTO classes. These are:
@Getter
– creates getters for members of a class@Setter
– creates setters for members of a class@RequiredArgsConstructor
– provides a constructor for final members of a class@ToString
– creates atoString()
method@EqualsAndHashCode
– createsequals()
andhashCode()
methods
All done automatically, without writing any boilerplate code!
As proof, we may open up the class structure view in our favorite IDE to see these methods signatures.
Person
Person class DTO contains five fields – firstname
, surname
, age
, height
, job
.
For this class, we will use @Getter
, @Setter
and @Builder
annotations.
import lombok.Builder; import lombok.Getter; import lombok.Setter; @Getter @Setter @Builder public class Person { private String firstname; private String surname; private int age; private int height; private Job job; }
@Getter
and @Setter
annotations are the same ones, that were added to our Job
class with @Data
annotation, just used explicitly.
The @Builder
annotation is more interesting. It uses a builder pattern, to add a brand new inner static class, that we can use for our Person class. One of the main advantages of using this annotation may be that if you have many fields in your constructors, it may be hard to differentiate them during initialization. Builder generated by Lombok provides us with named methods to set them, making creating instances of Person class more readable.
Example usage
Let’s see what all of these annotations in our classes give us, and how we can use them. For this purpose, we have created some tests in the main application class.
Job class example
Job furnitureCarpenter = new Job("carpenter"); furnitureCarpenter.setPosition("furniture"); furnitureCarpenter.setSalary(2500d);
In the example above, we have created an instance of a Job
class, using constructor provided by @Data
annotation. As we can see, only one argument is required, which is a final member of our DTO.
Next, we have used generated setters, to provide the rest of class member values.
To show that all of that nice functionality works, we may print out information about this object using automatically generated toString()
method:
System.out.println(furnitureCarpenter);
And the output is:
Job(job=carpenter, position=furniture, salary=2500.0)
To be complete about @Data
functionalities, we will also test equals()
and hashCode()
methods.
Job furnitureCarpenter = new Job("carpenter"); furnitureCarpenter.setPosition("furniture"); furnitureCarpenter.setSalary(2500d); Job sculptorCarpenter = new Job("carpenter"); sculptorCarpenter.setPosition("sculptor"); sculptorCarpenter.setSalary(2500d); System.out.println(furnitureCarpenter); System.out.println(sculptorCarpenter); System.out.println("Sculptor and furniture carpenters objects are the same -> " + (furnitureCarpenter == sculptorCarpenter)); System.out.println("Sculptor and furniture carpenters are the same -> " + furnitureCarpenter.equals(sculptorCarpenter)); System.out.println("Hash codes -> " + (furnitureCarpenter.hashCode() == sculptorCarpenter.hashCode())); sculptorCarpenter.setPosition("furniture"); System.out.println("Sculptor carpenter new specialization -> " + sculptorCarpenter.getPosition()); System.out.println("Sculptor and furniture carpenters objects are the same -> " + (furnitureCarpenter == sculptorCarpenter)); System.out.println("Sculptor and furniture carpenters are the same -> " + furnitureCarpenter.equals(sculptorCarpenter)); System.out.println("Hash codes -> " + (furnitureCarpenter.hashCode() == sculptorCarpenter.hashCode()));
We have created two carpenters with different positions, compared them, then changed one position to be equal to the second and compared them again. The results are below.
Job(job=carpenter, position=furniture, salary=2500.0) Job(job=carpenter, position=sculptor, salary=2500.0) Sculptor and furniture carpenters objects are the same -> false Sculptor and furniture carpenters are the same -> false Hash codes -> false Sculptor carpenter new specialization -> furniture Sculptor and furniture carpenters objects are the same -> false Sculptor and furniture carpenters are the same -> true Hash codes -> true
As we can see, Lombok’s magic works wonders!
Person class example
Person emily = Person.builder() .firstname("Emily") .surname("Stoke") .age(25) .height(172) .job(furnitureCarpenter) .build(); System.out.println(emily);
A builder example is fairly simple one. It creates the Person
object using a static PersonBuilder
class. To be able to display object information in a pleasant form, we should add @ToString
annotation to Person
class. The result of the code above is:
Person(firstname=Emily, surname=Stoke, age=25, height=172, job=Job(job=carpenter, position=furniture, salary=2500.0))
Summary
As we have shown in this article, Lombok is a great tool to have in a programmers pocket. Using annotations such as @Data
, @Setter
, @Getter
and @Builder
makes classes more concise and readable using some easy to grasp annotations. Of course, these are not all annotations that lombok provides. For more, please see the official Lombok website – https://projectlombok.org/.
The source code for this post can be found here on GitHub.