Say Good-Bye to Boilerplate Code with Lombok: Part 2-The Code

Hey! Tea Lovers! We will discuss How to use Lombok in our code. Its the continuation of our previous post “Say Good-Bye to Boilerplate Code with Lombok: Part 1-Installation“. In which we looked at what Lombok is and how to install it in Eclipse or IntelliJ IDEA. Now, we will look at how we can use the Lombok library in our code.

How to Use Lombok

To use Lombok please be ready with the installation and dependencies which we discussed in the previous part.

To use Lombok we use annotations. These specific annotations from the Lombok library generate code for us at compile time. We can use it on POJO for setters and getters, toString, or constructors. We can also generate a builder class so that we can set properties with the help of method chaining. Let us look at them briefly.

Setters and Getters

To generate setters and getters of properties you need to annotate the class with @Setter for set methods and @Getter for get methods. It will create setPropertyName(Object obj) and getPropertyName().

@Setter
@Getter
class SetterAndGetter{
    private int id;
    private String name;
    private ExtraClass extraClass;
}

class ExtraClass{

}
public class LombokCode {
    public static void main(String[] args) {
        SetterAndGetter sag = new SetterAndGetter();
        sag.setId(2);
        sag.setExtraClass(new ExtraClass());
        sag.setName("Some Name");

        System.out.printf("%d %s %s",sag.getId(),sag.getExtraClass(),sag.getName());

    }
}

As you can see it generated setters and getters for the fields.

Constructors

You can have multiple types of constructors for your class. Such as with all the fields, with final fields or no parameter at all with the help of @AllArgsConstructor, @RequiredArgsConstructor, and @NoArgsConstructor respectively. You can combine this with setters and getters also. But keep in mind that for non-static final fields, setters won’t be generated and cant use no-args-constructor. I mean you can play around it a bit and it will clear things out for you.

//without final fields
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
class NoAndAllArgConstructor{
    private int a;
}

//with final fields 
@AllArgsConstructor
@RequiredArgsConstructor
@Getter
@Setter
class RequiredAndAllArgConstructor{
    private final int a; //no setters since its final
    private String ab;
}

toString, equals, and hashCode()

@ToString is to create a toString() for you with all the fields present in the class. If we take the above-mentioned example’s RequiredAndAllArgConstructor class and mark it as @ToString then it will generate an output like this.

RequiredAndAllArgConstructor(a=10, ab=Example)

For equals and hashcode, it looks for all the fields. There is a lot going on in this case and can be found in detail here. In normal cases, it is ok to go with it but I would rather suggest using your own implementation for it if you are going to use it in specific cases such as a Map’s key or duplication is based on certain criteria. Anyhow, you just have to use @EqualsAndHashCode.

One Thing to Rule them All

Well, now you have lots of annotations in the class. And in lots of the cases, above-mentioned functions such as setters and getters, constructors, toString, equals, and hashcode will be used heavily. We don’t want to write these 4-5 annotations again and again. So here is the solution to use @Data. It is the combination of @Getter, @Setter, @ToString, @EqualsAndHashCode, and @RequiredArgsConstructor.

@RequiredArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode
class LotsOfAnnotations {
    private final int a;
    private String ab;
}
@Data
class OnlyData{
    private final int a;
    private String ab;
}

In the above code, you can see how the code’s length is reduced. And most of the time, @Data will suffice. But I would suggest using @AllArgsConstructor and @NoArgsConstructor. It may come in handy.

Method Chaining using Builder

Suppose you have lots of fields and you want to set a few of them. Now because not all the fields are being utilized it is hard to use all argument constructors and calling obj.set<propertyName>(value) for each property is troublesome and redundant. In this case, you can use @Builder. It creates a builder class for the current class. With the help of this, you can set values of multiple properties in a single pipeline like structure or method chaining. For better understanding please see below code.

@Builder
@ToString
class WithBuilderPojo{
    private final int id;
    private String name;
    private ExtraClass extraClass;
    private List<Float> listOfMarks;

    public static void main(String[] args) {

        WithBuilderPojo builder = WithBuilderPojo.builder()
                .id(1)
                .name("CodersTea")
                .extraClass(new ExtraClass())
                .listOfMarks(new ArrayList<>(0))
                .build();
        System.out.println(builder);
    }
}

Start the builder process by calling the static builder() method. Then with each, it will return the builder object. We need to set the properties with names (no prefix set). The order does not matter and you may skip fields if you want. And in the end, you have to call build() to create the object of the class otherwise you will end up with a builder object rather than required class.

Generate Log for Class

We can use Lombok not only in POJO but also in our other classes. For example, constructors can be created for dependent objects. One other thing is the log variable. Yes, Lombok can give you the log field. For log objects, all the things are the same in every class and the only change is the class name, correct? @Log eliminates this and generate it for you. There are specific annotations for each type of logger. Here are the few popular log type and their corresponding Lombok annotation.

A simple note, it generates the logger object with the name log.

java.util.logging.Logger@Log
org.slf4j.Logger@Slf4j
org.apache.commons.logging.Log@CommonsLog
Loggers and their corresponding Lombok annotations

@Slf4j is the one I personally used. Slf4j is a kind of API or abstraction for multiple logging frameworks. So you have the flexibility of changing the logger framework without changing the code. We will talk about it in a future post.

Other Annotations by Lombok

Lombok is keep on updating the library. I think above mentioned annotations are enough for you. There is @NonNull which throws the null pointer exception if the field is null. such as in constructor or any method.

Then there is @Var and @Val for mutable and immutable fields. I haven’t used it that much. Use val if you want to make the field final and var for normal field. No need to specify Object type. For example,

public static void main(String[] args) {
    //list is final now and class is automatically type casted.
    val list = new ArrayList<>(10);
    val name = "CodersTea.com";
    
    //variable
    var ExtraClass = new ExtraClass();

    for(var i = 0; i < 10; i++){
        System.out.println(i);
    }
}

Personally I don’t use them, val or var, since it’s not that beneficial for me. Anyways if you want you can use them and let me know in the comments how it has worked out for you.

Conclusion

This 2 part post has come to an end. In the 1st part, we saw what is Lombok and how to install it. This part, 2nd, was about Lombok annotations and the usage of various parts of it. In POJO you only need @Data, @AllArgsConstructor, @NoArgsConstructor, and @Builder in some cases. For other classes(services, controllers, etc) we can use constructor annotations and @Log or @Slf4j.

Hope you have enjoyed this long post about Project Lombok. Please share the post with others and comment your experience or any feedback. Also, read other interesting post from JavaSpring, and Best Practices. See you in next post.

Leave a Reply

Your email address will not be published. Required fields are marked *