Spicy Lombok library for your Java code - DO OK

Spicy Lombok library for your Java code

In this blog post, we share with you some benefits from using Lombok - a Java library that helps to decrease a boilerplate. You can see, how to use Lombok and discover some particular details you may don’t know yet. Also, you will find out if it’s possible to use this library with other languages.

Lombok is a Java library that “spices up” your code as you can read in its official website. In fact, it’s a collection of very useful annotations that allows you to forget about implementing e.g. your own constructors, setters, getters and toString or equalsAndHashCode methods. What is important, this lib has over 7 thousand stars on GitHub, so as you can see it could be a pretty reliable tool for your project.

  • @Getter
  • @Setter
  • @AllArgsConstructor

Let’s start with these 3 annotations which speak for themselves. Here is an example of how to use them:

import java.math.BigDecimal;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
class Bicycle {

    private String name;

    private BigDecimal value;

    private Wheel wheel;
}

And here’s an example of generated Bicycle class with these annotations after build:

import java.math.BigDecimal;

class Bicycle {
    private String name;
    private BigDecimal value;
    private Wheel wheel;

    public String getName() {
        return this.name;
    }

    public BigDecimal getValue() {
        return this.value;
    }

    public Wheel getWheel() {
        return this.wheel;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setValue(BigDecimal value) {
        this.value = value;
    }

    public void setWheel(Wheel wheel) {
        this.wheel = wheel;
    }

    public Bicycle(String name, BigDecimal value, Wheel wheel) {
        this.name = name;
        this.value = value;
        this.wheel = wheel;
    }
}

As you can see in the example, it provides you all getters, setters and also a constructor which requires all class’ fields as arguments. Ok, how about a constructor with no arguments? Here you go:

  • @NoArgsConstructor
  • @EqualsAndHashCode
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Setter
@NoArgsConstructor
@EqualsAndHashCode(of = "size")
class Wheel {

    private int size;

    private String type;
}

The above example shows also how to use @EqualsAndHashCode annotation. Thanks to that, non-primitive objects can be compared over their fields. I wanted my Wheel class to be comparable only by its “size” field. Anyway, look at the generated class:

class Wheel {
    private int size;
    private String type;

    public void setSize(int size) {
        this.size = size;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Wheel() {
    }

    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Wheel)) {
            return false;
        } else {
            Wheel other = (Wheel)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                return this.size == other.size;
            }
        }
    }

    protected boolean canEqual(Object other) {
        return other instanceof Wheel;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        int result = result * 59 + this.size;
        return result;
    }
}

In effect, Lombok provided a no-argument constructor and some helpful methods as I mentioned before like hashCode() and equals(). They check in their last condition if the objects have the same size fields.

  • @Builder
  • @NonNull

Another interesting annotation is definitely the @Builder. It provides a builder for a class which is an attractive alternative for creating a class. Let’s say we have a Rider class like below. It also presents the usage of @NonNull annotation.

import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;

@Getter
@Builder
class Rider {

    private String firstName;

    private String secondName;

    private Bicycle ownedBicycle;

    public void changeWheel(@NonNull final Wheel wheel) {
        if (!ownedBicycle.getWheel().equals(wheel)) {
            ownedBicycle.setWheel(wheel);
        }
    }
}

As a result, two simple annotations provide a number of methods which you can see below:

import lombok.NonNull;

class Rider {
    private String firstName;
    private String secondName;
    private Bicycle ownedBicycle;

    public void changeWheel(@NonNull Wheel wheel) {
        if (wheel == null) {
            throw new NullPointerException("wheel is marked @NonNull but is null");
        } else {
            if (!this.ownedBicycle.getWheel().equals(wheel)) {
                this.ownedBicycle.setWheel(wheel);
            }

        }
    }

    Rider(String firstName, String secondName, Bicycle ownedBicycle) {
        this.firstName = firstName;
        this.secondName = secondName;
        this.ownedBicycle = ownedBicycle;
    }

    public static Rider.RiderBuilder builder() {
        return new Rider.RiderBuilder();
    }

    public String getFirstName() {
        return this.firstName;
    }

    public String getSecondName() {
        return this.secondName;
    }

    public Bicycle getOwnedBicycle() {
        return this.ownedBicycle;
    }

    public static class RiderBuilder {
        private String firstName;
        private String secondName;
        private Bicycle ownedBicycle;

        RiderBuilder() {
        }

        public Rider.RiderBuilder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Rider.RiderBuilder secondName(String secondName) {
            this.secondName = secondName;
            return this;
        }

        public Rider.RiderBuilder ownedBicycle(Bicycle ownedBicycle) {
            this.ownedBicycle = ownedBicycle;
            return this;
        }

        public Rider build() {
            return new Rider(this.firstName, this.secondName, this.ownedBicycle);
        }

        public String toString() {
            return "Rider.RiderBuilder(firstName=" + this.firstName + ", secondName=" + this.secondName + ", ownedBicycle=" + this.ownedBicycle + ")";
        }
    }
}

As a result, Lombok created a static subclass RiderBuilder which has setters, no-args constructor, build() and a nice toString() method. Example how you can use the builder is below, but look again how @NonNull annotation changed the changeWheel() method with an annotated wheel parameter. It throws a NullPointerException with a message if the provided parameter is null.

Ok. The last step in this post we have to make is to check how we can use mentioned features, that these annotations provide, in practice. To demonstrate, I’ve created a Main class which uses all created before objects in its main() method.

import java.math.BigDecimal;

public class Main {

    public static void main(String[] args) {
        final Wheel smallWheel = new Wheel();
        smallWheel.setSize(22);
        smallWheel.setType("aluminium");

        final Wheel bigWheel = new Wheel();
        bigWheel.setSize(24);
        bigWheel.setType("carbon");

        final Bicycle bicycle = new Bicycle("Bianchi", new BigDecimal("10000.0"), smallWheel);

        final Rider rider = Rider.builder()
                .firstName("Alejandro")
                .secondName("Valverde")
                .ownedBicycle(bicycle)
                .build();

        rider.changeWheel(bigWheel);
    }
}

As can be seen, we have two Wheel objects. In the beginning, they’re created as an empty object, thanks to the @NoArgsConstructor. What’s more, their size and type could be set later thanks to the @Setter annotation. Another Bicycle class is created with all arguments put in its constructor (@AllArgsContructor). The last object is created by the builder. The @Builder has provided a static builder() method which creates an empty RiderBuidler class. Thanks to that we’re able to use generated setter methods on its class. The last step to do is to call build() method which gathers all RiderBuilder fields, creates the Rider class using these fields in a constructor and then returns it.

Other JVM languages

It’s worth to mention that since it’s a library written in Java, you could think that you can use it in any projects that use other JVM languages like Kotlin, Scala or Groovy. You can try and it’s possible that you’ll manage to do that in some cases, but I don’t recommend it. This lib gives some features for Java that many other languages, as mentioned above, already have. For example, Kotlin has it’s data class, Scala has case class and Groovy an annotation @Canonical. What is more, you might also have some problems with migrating Java project which uses Lombok to other JVM language or just with starting a new project in JVM language other than Java. Personally, I’ve never tried to do that, but there are many reports on the Internet from developers about problems during their attempts to integrate Lombok in their projects. Why? Here is an example: Kotlin uses javac like Java, but without annotation processing which is crucial for making a Lombok working. It’s because this lib is an annotation processor which means that it generates classes annotated with its features during the build of a project. So in result, Kotlin is not able to know what these annotations are before compiling. So, as you can see, trying might be a bit risky.

So, as you can see if you are planning to stick to Java then this library is a really good choice for you. Thanks to that you’ll boost your Java code and reduce an evil boilerplate. Well, at least partially.

What does the European Accessibility Act Mean for Your Business and How to Achieve Compliance
As digital experiences increasingly shape how we connect and engage, ensuring accessibi...
20.11.2024, min read
Anca Papainog
Read more
DO OK recognized as a Clutch Global Honoree and Champion for Fall 2024
Driven by a client-centric and flexible approach, DO OK has earned two recognitions fro...
15.11.2024, min read
Anca Papainog
Read more
Cookies

Our website has cookies. more info

EU Flag