Discover how AppDynamics steps in to upgrade your performance game and prevent your enterprise from these top 10 Java performance problems, brought to you in partnership with AppDynamics.
removes the need for you to code a lot of the standard boilerplate, such as "getters" and "setters", that have helped cause developers to leave Java, in favor of other languages. Using annotations provided by Lombok, your application's bytecode can be modified at runtime, as explained below in an interview with Reinier Zwitserloot and Roel Spilker, the two developers behind Lombok.
First of all, can you say a few things about who you are?
My name is Reinier Zwitserloot. I spend most of my time developing and marketing my startup, tipit.to
, which lets you put tip jars (for donations) on any website. In my free time, I like to work on projects that
seem like fun. Not just Lombok, but also, for example, massively
multiplayer minesweeper or wiring up an exercise bike to a computer.
I am Roel Spilker. During the day I spend my time working at
on a Service Management Tool. Most of my fun projects are
software or electronics related.
Before we go further, why is Lombok called Lombok?
Java projects usually riff on the idea that Java is a coffee
related concept. However, Java is also an island in the Indonesian
archipelago. If you move east from Java, you first hit Bali. East of
Lombok is also Indonesian for chilli, and is used in
some parts of the world as a synonym for chilli, even outside of Indonesia. This gives us a nice opportunity for a logo... and ties into
the tag line "Spicing up your Java".
Lombok was very enthusiastically received at Devoxx this year. It seems
to be a pretty new thing, since the v0.9.2 "Hailbunny" release is now in beta. What's the
history of Lombok?
This past week I was looking through a few of my old projects and
ran across a site Roel and I put up way back in early 2005, with some
suggestions for Java, in response to a call for ways to reduce
boilerplate in Java 6 by Graham Hamilton (it's still live, at http://java-boilerplate.blogspot.com/
It includes @Getter and @Setter, and also something that looks a lot
like the CICE closures proposal, so I guess both Roel and I have been
thinking about boilerplate busting features for Java for a long time.
Another concept we thought about was an IDE plugin that hides
boilerplate in the source view (for example, render a standard getter
as @Getter on a field, like Lombok supports), and even lets you type
like this, but saves back to a vanilla Java file so other people on
your team, and any other tools that work with your source file, aren't
affected. We dropped this idea when we realized there were too many
hurdles (such as: how do we prevent a getter from moving around,
mucking up your source control commit logs). It's very similar to Lombok, though.
Sometime in the middle of last year, I was chatting
with Perry Nguyen on ##java (IRC java channel on freenode), and I
mentioned some of these ideas. He showed me a simple proof of concept
that used some creative casting to implement something similar to
@Getter and @Setter on just Java.
Roel and I fleshed this out into a complete engine
and then set to work on figuring out how to add support for Eclipse (we
are both Eclipse users). We couldn't make it work with Perry's trick,
but at this point we were sufficiently committed that we kept searching
for a way, and eventually worked it out using Lombok's current approach
to supporting both Eclipse and NetBeans: Java agents.
According to the git repository, the first release
we put on the website was tagged on the 26th of July, so Lombok is
still a very new project. I'm not sure of the exact date, but Roel and
I did the bulk of the work for that first public release (v0.8.1,
mostly named in honor of our earlier failed attempts to create
something like this) in 2 weeks of pair programming every evening.
Can you give us a brief overview of all the annotations and what they do?
- @Getter, @Setter, @ToString, @EqualsAndHashCode,
and @Data all fill in the usual boilerplate that your IDE can generate
for you as well via the source menu (getters, setters, a toString that
prints fields, and equals and hashCode implementation that compares
fields, and a constructor that has a parameter for each final field).
With the Lombok annotations, you don't have to see (or write, or
maintain!) all this boilerplate, which can really add up:
- There's also @Cleanup. You annotate a local
variable that needs to always be closed in order to avoid resource
leaks (such as, say, FileOutputStream, or socket.getInputStream(), or a
JDBC ResultSet), and Lombok takes care of it for you. All statements
following the declaration, up to the point where that variable name
goes out of scope, are compiled as if they are in a try block, with an
accompanying finally block that calls close() on the resource.
I actually use @Cleanup the most myself, but a show
of hands at our Devoxx talk shows that @Data is the clear winner
amongst Lombok users.
- Lombok also has
@Synchronized, which is just like the 'synchronized' keyword on
methods, except it'll create a private final field with a private lock,
instead of locking on 'this', which could lead to unforeseen deadlocks
if other code also locks on your object.
- Finally, there's @SneakyThrows. The concept of a
checked exception is actually just a javac feature. Similar to generics
erasure, at the JVM level, checked exceptions don't exist; any
exception, checked or unchecked, can be thrown anywhere, regardless of
try/catch blocks or 'throws' clauses on methods. Jython, Scala, JRuby,
and most other languages that run on the JVM don't have checked
exceptions either, which is why these languages still work on the JVM.
@SneakyThrows gives you this power for Java; you annotate your method
with for example @SneakyThrows(IOException.class), and the compiler
will stop complaining that you need to handle IOExceptions in that
method. I've seen a lot of code where checked exceptions are simply
swallowed, or logged. Throwing these exceptions onwards is almost
always better than ignoring them, though for example interface
restrictions can get in the way, so @SneakyThrows gives you a way out.
Can we expect new boilerplate busters in the future? Roel:
can! There are two features that come to mind immediately: @Delegate
and @Mixin. The first has to do with composition, and really shows its
strengh when you use the decorator pattern. If you annotate a field
with @Delegate, all methods of the type of the field will be generated
in the class the field is in, and the implementation will just delegate
the call to the field.
The second, @Mixin, will let you easily
add behavior to your class, based on your own public API. So, if your
class implements Comparable, you can mix-in the methods greaterThan,
lessThan, etc. These methods will internally call compareTo.
What's going on under the hood? I.e., how does an annotation result in the boilerplate ending up in the bytecode?
The annotation processor API only lets you create new files, it
does not let you modify the file that has the annotation inside of it. Which
is what Lombok does, so Lombok does not use the annotation processor
Instead, Lombok uses the annotation processor API
only as a mechanism to inject itself into the compilation process. All
annotation processors are initialized early in the compilation process,
and Lombok modifies javac when it is initialized as an annotation
processor. We change only one thing: The AST (the raw source code,
parsed into a tree form) is first handed off to Lombok, which generates
whatever needs to be generated, before javac continues.
We do something similar in Eclipse, except that in IDEs
it's a bit more complicated. Annotation processors run, at best, when
you save the file, but IDEs do a lot more than compile code. They show
syntax errors as you type, they have an auto-complete dialog, refactor
scripts, and features like 'jump to declaration', all of which need to
be aware of something like a @Getter annotation. So, in Eclipse, we use
a Java agent. Java agents are offered the chance to modify bytecode
before the JVM loads a class. Lombok, when running on Eclipse or
NetBeans, will actually rewrite the parser code and insert a call into Lombok with the AST, so that all IDE functions that work on the AST,
from compiling, to syntax checking, to auto complete dialogs, get the
proper ASTs with all generated methods in them.
When would and when would it not make sense to use Lombok? For example, is it for production scenarios only?
If I take my @Override annotations away, my code will still work.
However, if I take my Lombok annotations away, I have a lot of work
ahead of me in adding boilerplate code. In other words, doesn't Lombok
break some implicit rules of annotations?
the class files produced from a source file with Lombok annotations in
it are indistinguishable from class files produced from source files
written out in full, so Lombok can certainly be used in production
code. The biggest reason not to use it is if someone on your team uses
IntelliJ IDEA, or some other IDE that isn't Eclipse or NetBeans, as Lombok doesn't work on other IDEs (yet!)
A second issue is that Lombok requires javac 1.6,
but this is not that big of a deal for us, as Java 1.5 has been
end-of-lifed some months ago.
There are also
some corner cases in the IDEs that we haven't fully solved yet. For
example, if you try to run the 'extract method' refactor script on code
that is inside a @Synchronized method, you get an Eclipse error instead
of refactored code. We're working on fixing these as we find them, but
if you use Eclipse's refactor scripts a lot, you may want to avoid
@Cleanup and @Synchronized in particular.
Other than that, resource cleanup and easy
struct-like classes really change how you code. I've seen a lot of
projects use some form of a 'Pair' class, for example, to allow a
method to return 2 values. However, in almost all cases, a unique class
to hold these two values would be the nicer design, but it's too much
effort to create this class. With Lombok, the effort is minimal, and as
a result you end up writing better code. So, we encourage everyone to
Yes, it does. However, in the unlikely
scenario this causes problems, the v0.9.2 "Hailbunny" release, currently in beta, includes the
"delombok" tool, which will remove all traces of Lombok from your code.
It takes source files containing for example: "@Getter private int x;"
and spits out a source file with the annotation removed, and the getX()
How has Lombok been received thus far? Can you give us a few examples of the varying responses? Reinier:
more positive than we originally thought when we released it. Because
the Java community is so large, any language change of any sort is
usually met with a lot of resistance. For example, discussions about
checked exceptions are usually quite fierce, but @SneakyThrows, which
has one foot in the door of abolishing them altogether, isn't
criticized nearly as much as I expected.
The Sun core team that works on language changes
(Joe Darcy and Alex Buckley, for example) were pretty negative at first,
but we talked to them at Devoxx, and they made some good points, and
we laid out some plans on how to address some of them. In the meantime, the NetBeans team has provided crucial patches that have enabled
us to write the beta NetBeans support in record time (Thanks, Jan
Lahoda!), as well as a patch to support Lombok in the latest version of
JDK7's javac, so we seem to have fans within Sun as well.
Dick Wall and the rest of the Java Posse
championing Lombok, probably because the posse has been looking a lot
at alternative language on the JVM recently, like Scala. Lombok
basically ports some of the nice parts of other languages to Java. For
example, @Data is very similar to Scala case classes.
What are the main highlights of the v0.9.2 "Hailbunny" release, currently in beta, and how did those come about?
The v0.9.2 "Hailbunny" release, currently in beta, has tons of new features.
The current release on the website is pretty stable. However, for the
next release, called Hailbunny, there is a lot of new and exciting
stuff. Here's the list:
- Preliminary NetBeans support.
- JDK 7 support.
- Delombok, to allow source-processors like the javadoc tool and the GWT-compiler to work with lomboked code.
- Improved Eclipse support, for which we created a new patcher-framework.
- Enhanced current features.
The JDK 7 and NetBeans support listed above are due to patches from Jan Lahoda
(from the NetBeans team). "delombok" is something Roel had been working
on for a while, and has been part of our plan for Lombok from the
beginning. He's recently had some time to finish it.
Another consequence of "delombok" is that we've been
adding a lot of integration tests. We can now use "delombok" to
automatically compare Lombok's transformations against a hand-written
source file that should be equal.
We're considering releasing it as v0.10 instead of 0.9.2.
that the beta of the v0.9.2 "Hailbunny" release is out, what needs to happen for the full release to be
pushed out the door? And what about the releases after that? Reinier:
probably do the Google thing and remain in beta for a long time. We
aren't ready to christen a Lombok release as 'v1.0.0' until:
- We support all 3 major IDEs: Eclipse, NetBeans IDE, and IntelliJ IDEA.
- We've sorted out all the corner cases; every refactor script should work.
- We have IDE plugins for all three major IDEs, offering new refactor scripts
unique to Lombok (such as: refactor a getter into a @Getter annotation,
for example), as well as a feature to show the result of Lombok's
transformations so you can tell exactly what's going on.
- The API for writing your own transformations is stable.
- We are certain that the annotations that Lombok supports don't ever need to undergo a breaking change.
as Lombok is purely a compiler/IDE assistant, a beta Lombok does not
prevent you from using it. You can always stop using Lombok by running
your code through "delombok", and the class files that you use in a
production environment are no different than what you'd have ended up
with if you hadn't used Lombok to begin with.
Would you like code contributions from the broader community and, if so, in which specific areas?
Oh, yes, absolutely, we loooove code contributions.
particular, in areas of other IDEs and code tools that we don't yet
support. Those NetBeans patches were pretty much on the top of our
patches wishlist. If some intrepid IntelliJ expert sends us patches for
that, we'd be as happy as pigs in mud. Also, patches that fix some of
the corner cases in IDEs we do support are also very welcome.
But, mostly, if you run into weird cases, send in a
bug report. We've made it very simple and you don't need to sign up for
anything. Just go to projectlombok.org
and click 'Report an Issue'.
Thanks Reinier and Roel... and all the best with the further development of this great tool!
The Java Zone is brought to you in partnership with AppDynamics. AppDynamics helps you gain the fundamentals behind application performance, and implement best practices so you can proactively analyze and act on performance problems as they arise, and more specifically with your Java applications. Start a Free Trial.