Using Lombok in Spring Boot to Reduce Boilerplate Code

Lombok is an excellent library for reducing boilerplate code in Java applications, including Spring Boot projects. It provides useful annotations that simplify mundane tasks like generating getters, setters, constructors, hashCode, equals, and toString methods.

Here’s how to use Lombok in a Spring Boot project to make your code cleaner and more concise:

Steps to Use Lombok in Spring Boot

  1. Add Lombok Dependency
    Add the Lombok dependency to your (for Maven) or build.gradle (for Gradle). pom.xml
    Maven:

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.30</version> <!-- Check for the latest version -->
        <scope>provided</scope>
    </dependency>
    
  2. Enable Annotation Processing
    Ensure that annotation processing is enabled in your IDE (e.g., IntelliJ IDEA).
    In IntelliJ IDEA:

    • Go to File > Settings > Build, Execution, Deployment > Compiler > Annotation Processors.
    • Check Enable annotation processing.
  3. Add Lombok Annotations in Your Code
    Use Lombok annotations in your classes to reduce boilerplate code. The most commonly used annotations are described below.

Commonly Used Lombok Annotations

  1. @Getter and @Setter
    Automatically generates getter and setter methods for your fields.

    import lombok.Getter;
    import lombok.Setter;
    
    @Getter
    @Setter
    public class User {
        private Long id;
        private String name;
    }
    
  2. @ToString
    Automatically generates a toString() method for the class.

    import lombok.ToString;
    
    @ToString
    public class User {
        private Long id;
        private String name;
    }
    
  3. @EqualsAndHashCode
    Generates equals() and hashCode() methods.

    import lombok.EqualsAndHashCode;
    
    @EqualsAndHashCode
    public class User {
        private Long id;
        private String name;
    }
    
  4. @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor
    Generates constructors:

    • @NoArgsConstructor: No-args constructor.
    • @AllArgsConstructor: All-args constructor.
    • @RequiredArgsConstructor: Constructor for required fields (final fields or fields with @NonNull annotation).
    import lombok.AllArgsConstructor;
    import lombok.NoArgsConstructor;
    import lombok.RequiredArgsConstructor;
    
    @NoArgsConstructor
    @AllArgsConstructor
    @RequiredArgsConstructor
    public class User {
        private Long id;
        @NonNull
        private String name;
    }
    
  5. @Data
    A shorthand annotation that combines @Getter, @Setter, @ToString, @EqualsAndHashCode, and @RequiredArgsConstructor.

    import lombok.Data;
    
    @Data
    public class User {
        private Long id;
        private String name;
    }
    
  6. @Builder
    Enables the builder pattern for the class.

    import lombok.Builder;
    
    @Builder
    public class User {
        private Long id;
        private String name;
    }
    
  7. @Slf4j
    Adds a static logger variable (log) for logging purposes.

    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class UserService {
        public void performAction() {
            log.info("Performing some action...");
        }
    }
    

Example: Lombok in a Spring Boot Entity

Below is an example of a Spring Boot entity class that uses Lombok annotations:

package com.example.demo.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
}

Logging Example

Service class adding logging with Lombok’s @Slf4j:

package com.example.demo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class UserService {
    public void processUser() {
        log.info("Processing user...");
    }
}

Advantages of Using Lombok

  1. Significant reduction in boilerplate code, making your classes cleaner and easier to read.
  2. Easier maintenance since redundant code is removed.
  3. Integration with Spring Boot makes it seamless to use.

How do I define access modifiers in Lombok’s @Getter and @Setter annotations?

By default, when we use the Lombok’s @Getter and @Setter annotations the getters and setters will be created with public access modifier. We can however change the access modifier by setting the AccessLevel of the @Getter and @Setter annotations. The available choices for the access level are AccessLevel.PUBLIC, AccessLevel.PROTECTED, AccessLevel.PACKAGE, AccessLevel.PRIVATE. These enum values correspond to Java’s access modifier. While the AccessLevel.NONE will disable the getter and setter method generation.

package org.kodejava.lombok.support;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Person {
    @Setter(AccessLevel.PROTECTED)
    private String firstName;

    private String lastName;
    private String gender;

    @Getter(AccessLevel.PRIVATE)
    private int age;
}

How we use the Person class show in the snippet below:

package org.kodejava.lombok;

import org.kodejava.lombok.support.Person;

public class PersonDemo {
    public static void main(String[] args) {
        Person person = new Person();
        person.setLastName("Bar");
        person.setGender("M");
        person.setAge(20);

        System.out.println(person.getFirstName());
        System.out.println(person.getLastName());
        System.out.println(person.getGender());
    }
}

If we try to see the generated class of the Person class we can run the following command to disassemble the class.

javap -p -cp . org.kodejava.lombok.support.Person

And we got the following output of the javap command. As we can see that the setFirstName() method have a protected access modifier and the getAge() method have a private access modifier. The other mutator and accessor method all set to public access modifier.

public class org.kodejava.lombok.support.Person {
    private java.lang.String firstName;
    private java.lang.String lastName;
    private java.lang.String gender;
    private int age;
    public org.kodejava.lombok.support.Person();
    public java.lang.String getFirstName();
    public java.lang.String getLastName();
    public java.lang.String getGender();
    public void setLastName(java.lang.String);
    public void setGender(java.lang.String);
    public void setAge(int);
    protected void setFirstName(java.lang.String);
    private int getAge();
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </dependency>
</dependencies>

Maven Central

How do I generate getters and setters with Lombok?

The following code snippet show you how to use Project Lombok‘s @Getter and @Setter annotations to generate getters and setters method in your POJO (plain old java objects) classes. Using these annotations remove the need to manually implements the mutator and accessor methods. Although most IDE allows you to generate these methods, using Lombok makes your classes look cleaner, especially when you have a long list of fields.

Here is a simple User class with a handful fields. We will use the @Getter and @Setter annotations on the class level. This will generate the getters and setters method for any non-static fields in the class.

package org.kodejava.lombok.support;

import lombok.Getter;
import lombok.Setter;

import java.time.LocalDate;

@Getter
@Setter
public class User {
    private Long id;
    private String username;
    private String password;
    private LocalDate lastLogin;
    private boolean active;
}

Each fields in the class will have its corresponding getter and setter. For example the username field will have the getUsername() and setUsername() method. If the field type is boolean such as active it will generate the method setActive() and isActive() method.

Because the accessor and mutator already handled by Lombok, we can use the User class as if we manually implement the getters and setters method.

package org.kodejava.lombok;

import org.kodejava.lombok.support.User;

import java.time.LocalDate;

public class UserDemo {
    public static void main(String[] args) {
        User user = new User();
        user.setId(1L);
        user.setUsername("foo");
        user.setPassword("secret");
        user.setLastLogin(LocalDate.now());
        user.setActive(true);

        System.out.println(user.getId());
        System.out.println(user.getUsername());
        System.out.println(user.getPassword());
        System.out.println(user.getLastLogin());
        System.out.println(user.isActive());
    }
}

If for some reasons you want to disable the getter and setter on specific field, or you want the change the access level, you can use the AccessLevel enums value for the @Getter and @Setter annotations. For example in the code snippet below the username will have no getter and setter while the lastLogin getter and setter will have protected access modifier. The AccessLevel enums includes PUBLIC, MODULE, PROTECTED, PACKAGE, PRIVATE and NONE.

package org.kodejava.lombok.support;

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDate;

@Getter
@Setter
public class User {
    private Long id;
    @Getter(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    private String username;
    private String password;
    @Getter(AccessLevel.PROTECTED)
    @Setter(AccessLevel.PROTECTED)
    private LocalDate lastLogin;
    private boolean active;
}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.28</version>
    </dependency>
</dependencies>

Maven Central