Banish Repetitive Java Code with Lombok

Lombok is an island. Here is a random pic from it: “woman on seashore” by Faizal Abidin on Unsplash

Remember the countless times you felt frustrated while writing Getters and Setters, and you felt POJO (Plain Old Java Objects) sucked. Well, you are not the only one. Countless developers have spent countless hours typing boilerplate code without any productive output.

I started my programming career with Java. I have written thousands of LoC (including 50% boilerplate) with no complaints. But, I have been away for Java for almost two years, writing Python, Go and JavaScript almost exclusively, and the repetitive boilerplate made my return really unpleasant.

Granted, IDEs automate some code for us. But why! It still needs shortcuts and mouse clicks which, I feel, disrupts my flow of thoughts.

Lombok to resuce

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java. Never write another getter or equals method again

Taken straight from Project Lombok’s homepage. It is the library everyone needs to use. It is the magic potion.

Jokes apart. It is a library of annotations which make writing code in Java bearable. Java is a great language but it’s verbosity is an annoyance to many.

Let me summarize some of the awesome super spices Lombok contains:

  1. Getter and Setter annotations automatically generate Getters and Setters for your Java beans.
  2. NoArgsConstructor and AllArgConstructor allow to add constructors to your POJOs in no time.
  3. ToString makes every POJO Logger and print friendly.
  4. Data makes your POJO skeleton as a complete spec-compliant POJO.
  5. SneakyThrows allows you to suppress the requirement of trying every single checked exception, even at places where you know such exceptions will never happen.

Here is a list of all Lombok features available!

How does Lombok work?

It works with the help of Java annotation processor and a handful of compile-time annotations. It injects additional Java bytecode that handle the repetitive code for us. You can even view the generated Java code by a process humorously called “Delombokisation”.

How do I get started?

Lombok introduces an additional compile time dependency.

If you are compiling with the vanilla javac, you will need to specify lombok.jar, found here, as a compile time annotation processor: javac -cp lombok.jar MyCode.java

If you are using maven then the following dependency in the pom.xml will make your code Lombok ready

<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
</dependencies>

Of if you are using Gradle then use the Gradle Lombok plugin:

plugins {
id 'io.franzbecker.gradle-lombok' version '1.14'
id 'java'
}

Since you are using Java, you will also be using a smart IDE that auto compiles code or provides code suggestions. In order to integrate Lombok with them, you will need to tell Lombok io install appropriate hooks to those.

Running java -jar lombok.jar after fetching the Lombok jar will setup all the things.

IntelliJ IDEA and Visual Studio users will need a separate “Lombok” plugin available from respective plugin repositories.

Gimme the code!

Yes here is it. A complete example demonstrating all features.

Generates getXXX and setXXX for the annotated fields.

import lombok.Getter;
import lombok.Setter;
class UptimeResponse {
// GetXXX and SetXXX are automatically generated
@Getter @Setter private long uptime;
@Getter @Setter private long currentTime;
@Getter @Setter private String status;
UptimeResponse() {
this.uptime = ManagementFactory
.getRuntimeMXBean().getUptime();
this.currentTime = System.currentTimeMillis();
this.status = "OK";
}
}
// So this works automagicallyUptimeResponse res = new UptimeResponse();
res.setStatus("FAIL");
System.out.println(res.getUptime()); // 12332

Default POJO constructors can be automatically be created, which initialize the fields to default values.

  1. A NoArgConstructor creates one that assigns default values to all fields.
  2. AllArgsConstructor creates a constructor that allows to specify values to all fields.
  3. RequiredArgsConstructor generates constructor for all fields which are final or marked as NotNull.
import lombok.*@AllArgsConstructor
class Document {
@Getter @Setter private String title;
@Getter @Setter private String content;
// ...
}
// This works automagically
Document d = new Document("Hello World", "Message Body");
d.getTitle(); // Hello World
d.getContent(); // Message Body

Another common boilerplate that Lombok automates is equality and hash code generation by including the local variables. You can even mark certain variables for exclusion.

import lombok.*;@RequiredArgsConstructor
@EqualsAndHashCode
class User {
@Getter
private final String username;
@EqualsAndHashCode.Exclude
@Getter
@Setter
private String lastAction; // not required for equality checks
}
// This works automagicallyUser u1 = new User("amitosh");
u1.setLastAction("Hello");
User u2 = new User("amitosh");
u2.setLastAction("Compile");
u1.equals(u2) // Gives true

Lombok ToString annotation automatically generates a toString method for the class encapsulating all fields. It is a quick way to generate debug representations.

import lombok.ToString;
import lombok.Getter;
import lombok.Setter;
@ToString
class Entry {
@Getter @Setter private String id;
@Getter @Setter private String target;
}
// This works automagicallyEntry e = new Entry();
// ...
System.out.println(e); // Nice output with values of id and target

This was created with POJO classes in mind. A shortcut for ToString, EqualsAndHashCode, Getter on all fields and Setter on all non-final fields.

import lombok.Data;@Data
class Message {
private String sender;
private String content;
}
// This works automagicallyMessage m = new Message("amitosh", "Hello World");
m.setSender("agathver");
m.getContent(); // Hello World
m.toString(); // ...

Java uses checked languages, which is good, but sometimes it is excess — the run method in Runnable where we are not interested in the exception (we can attach an uncaught exception handler) or in situations where we are sure that the exception will never occur. SneakyThrows provides an escape hatch. It allows you to skip the stringent conditions by faking the compiler.

However, misusing this is not a good thing. You have been warned.

import lombok.SneakyThrows;

public class SneakyThrowsExample {
@SneakyThrows(UnsupportedEncodingException.class)
public String utf8ToString(byte[] bytes) {
// This exception is never generated as UTF-8 is guaranteed
// to be supported by the JVM
return new String(bytes, "UTF-8");
}
}

Delomboking

Not all tools support Lombok, most notable being the JavaDoc tool. You will need an intermediate representation in order to prepare the correct docs. Also sometimes you may wish to inspect what code does Lombok actually generate for you. Fortunately Lombok provides “delomboking” — generating Java source code with Lombok transformations applied.

To transform a complete folder use:

java -jar lombok.jar delombok src -d src-delomboked

The maven and gradle plugins also contain delomboking task definitions, should you ever need to use them.

Lombok is another tool to improve your Java productivity. I cannot imagine myself programming Java without it these days. I really hope you discovered its power reading this article!

Computer Whisperer. Open-source contributor. Find me at https://amitosh.in/