Using Project Lombok with Gradle

Using Project Lombok with Gradle

0 Comments

Introduction

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 a toString() method
  • @EqualsAndHashCode– creates equals() and hashCode() 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.

About SFG Contributor

Staff writer account for Spring Framework Guru

    You May Also Like