Java and Lombok are close to each other. Maybe too close ? :)

Some Dangers of Using Lombok

Gábor Lipták
4 min readJun 15, 2018

--

What is Lombok? According to its homepage:

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. Early access to future java features such as
val, and much more.

I happened to become a user of Lombok in an existing codebase. After some fustrating hours let me share some thoughts about its dangers, which I became aware of.

“automatically plugs into your editor and build tools, spicing up your java”

O o. That might sound promising, but such slogans are suspicious to me. Using a middle sized project my collegue happened to face with the same problem, which was reported a few weeks ago. After typing a character he had to wait a few seconds, since Eclipse became frozen.

After we took some threaddumps using JVisualvm we realized, that each time Eclipse hangs, Lombok does its magic Eclipse’s Abstract Syntax Tree. Inside the GUI thread, which is a bad practice, since for long running stuff we should use background worker threads.

A second observation I made during my work with a bigger project with a lot of JSF XHTML files and Lombok Beans. After removing Lombok from the project the build time was reduced to its ~33%! I suppose the validation of the expressions in JSF files relies havily on examining the getters and setters of classes, and thats why it has such an impact.

The integration with Eclipse is anyway not perfect. If we want to see the callers of a setter or getter, we cannot do so, since there is no such method in the editor to right click on. The only workaround I know is to open the outline and there we can look for the method and in the local menu call hierarchy can be triggered.

If I want to see, why two objects are not equal, I have lost again. I can set a method breakpoint, but I have no idea on which code lines I debug step by step. Again, pain. I can delombok the code and then debug, but then why should I use Lombok anyway? I recently decompiled a class just to see, which step inside the equals method results in a “false” return value.

“Never write another getter or equals method again”

Funny thing. Equals and hashCode. Real life example will be presented :)

Setting callSuper to true when you don't extend anything (you extend java.lang.Object) is a compile-time error, because it would turn the generated equals() and hashCode() implementations into having the same behaviour as simply inheriting these methods from java.lang.Object: only the same object will be equal to each other and will have the same hashCode. Not setting callSuper to true when you extend another class generates a warning, because unless the superclass has no (equality-important) fields, lombok cannot generate an implementation for you that takes into account the fields declared by your superclasses.

My example is a simple parent class with a subclass.

So both foo and bar are the same, still according to the generated equals method they are not equal.

Here I think Lombok is simply wrong. It should always give a compile error, if my class extends anything having the default hashcode method (not only for java.lang.Object itself, like in the quote above).

I think earlier someone tried this cool feature “callSuper”. Default value is false. He or she has seen, oops. I got a warning… Ok, lets make it true, then it works…

If we use a hammer, we should know exactly how it works. Since WrongEntityExample has the callsuper set to true, it will call the equals method of the POJO class, which is the default implementation. That gives only true back if the two references refer to the same object. So I can construct any number of WrongEntityExample, they will be never equal to each other.

The correction is simply setting callSuper to false:

Having a wrong equals and hashcode pair can result in serious problems, since the whole collection framework is based on them.

Lombok and its possible Side Effects

These things are not caused by Lombok, but by using it inappropiate. Still Lombok makes it easy to be used inappropiate.

Lets suppose I have a bean like this:

At first I had only fooo and bar as members and only bar was used in equals and hashcode.

Then some day, a developer makes some internal calculation and caches it in the myInternalCalculationResult. He forgets to exclude the field and the internal state of the SideEffectExample class is directly exposed with a setter and getter. Thats bad. Without Lombok it would not happen, since I have a reflex to make all fields private by default and I do not generate automatically getters and setters like Lombok.

After that thisIsSomeCachedValue is added, which as the name supposes has nothing to do with the equality of the object. Still it will be silently involved into the equality check and ruins probably everything. Again this does not happen without Lombok, since it would not be included automatically otherwise.

Why Lombok?

At the age of IDEs why do I need Lombok at all? Is it that hard to generate the getters, setters, hashCode or equals using my IDE with 2 clicks? Do I need something that silently “integrates” into my build process and development environment? Is it really harder to write a line containing the logger than using a Lombok annotation? Do I want to spare some work on the one hand just to make more work with delombok on the other hand? Do I want to use something, which uses the Java Compiler in an unintended way? Do I need such magic?

My personal answer is no. Thanks. I do not need Lombok.

Code: https://github.com/liptga/lombokdemo

UPDATE: for unresponsive Eclipse I have found a solution. See https://github.com/rzwitserloot/lombok/issues/1717#issuecomment-427349381

--

--