Lombok is a real time saver at times but it can also lead to unexpected bugs in your code. Here, I've described some of the caveats I've encountered.
StackOverflow in @ToString
@ToString can give
you stack overflow if it's lored into an infinite loop. One place
where this can easily happen, is if you have javax.persistence
entities that have fields with many to one relationships.
The remedy is to include those fields in the optional exclude parameter of the annotation:
@ToString(exclude = "tribe")
@Entity
public class Indian
{
@ManyToOne
private Tribe tribe;
}
@ToString(exclude = "indians")
@Entity
public class Tribe
{
@Getter
@OneToMany(mappedBy = "tribe")
private List<Indian> indians = new ArrayList<>();
}
Equals can trick you if you have proxied member variables
Again, this is a caveat if you have a @EqualsAndHashCode
on your
javax.persistence
entity and this entity has a many to one/one to
many field.
The remedy is to implement the equals()
method yourself.
Creating a builder while keeping a default constructor
I've come to love the @Builder annotation:
@Builder
public class IceCream {
private int size;
private Color color;
}
Allowing me to create instances using the builder flow:
IceCream iceCream = IceCream.builder().
size(10).
color(Color.RED).
build();
This is all well and good, but some frameworks (like JPA) needs a
default constructor. However, the @Builder
annotation makes these
throw nasty exceptions at you like:
Caused by: java.lang.NoSuchMethodException: net.skybert.IceCream.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
The reason is that when annotating a class with @Builder
an
@AllArgsConstructor
is implied. However, some frameworks need the
default constructor to work, so we'll need to add both the Lombok
@NoArgsConstructor
and @AllArgsConstructor
annotations to get the
behaviour we want with the frameworks while getting the goodness of
Lombok's @Builder
. The class then looks like this:
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class IceCream {
private int size;
private Color color;
}
Easy enough when you know it 😎