MyPage is a personalized page based on your interests.The page is customized to help you to find content that matters you the most.


I'm not curious

Write Fat-free Java Code with Project Lombok

Published on 13 March 17
1075
1
1

There are a number of tools and libraries I cannot imagine myself writing Java code without these days. Traditionally, things like Google Guava or Joda Time (at least for the pre Java 8 era) are among the dependencies that I end up throwing into my projects most of the time, regardless of the specific domain at hand.

Lombok surely deserves its place in my POMs or Gradle builds as well, albeit not being a typical library/framework utility. Lombok has been around for quite a while now (first released in 2009) and has matured a lot since. However, I have always felt it deserved more attention—it is an amazing way of dealing with Java’s natural verbosity.

In this post, we will explore what makes Lombok such a handy tool.
Write Fat-free Java Code with Project Lombok - Image 1

Java has many things going for it beyond just the JVM itself, which is a remarkable piece of software. Java is mature and performant, and the community and ecosystem around it are huge and lively.

However, as a programming language, Java has some idiosyncrasies of its own as well as design choices that can make it rather verbose. Add some constructs and class patterns we Java developers often need to use and we frequently end up with many lines of code that bring little or no real value other than complying with some set of constraints or framework conventions.

Here is where Lombok comes into play. It enables us to drastically reduce the amount of boilerplate code we need to write. Lombok’s creators are a couple of very smart guys, and certainly have a taste for humor—you cannot miss this intro they made at a past conference!

Let’s see how Lombok does its magic and some usage examples.
1
How Lombok Works

Lombok acts as an annotation processor that adds code to your classes at compile time. Annotation processing is a feature added to the Java compiler at version 5. The idea is that users can put annotation processors (written by oneself, or via third-party dependencies, like Lombok) into the build classpath. Then, as the compile process is going on, whenever the compiler finds an annotation it sort of asks: Hey, anybody in the classpath interested in this @Annotation?. For those processors raising their hands, the compiler then transfers control to them along with compile context for them to, well… process.

Maybe the most common case for annotation processors is to generate new source files or perform some kind of compile-time checks.

Lombok does not really fall into these categories: What it does is modify the compiler data structures used to represent the code; i.e., its abstract syntax tree (AST). By modifying the compiler’s AST, Lombok is indirectly altering the final bytecode generation itself.

This unusual, and rather intrusive, approach has traditionally resulted in Lombok being viewed as somewhat of a hack. While I would myself agree with this characterization to some extent, rather than viewing this in the bad sense of the word, I would view Lombok as a clever, technically meritorious, and original alternative.

Still, there are developers who consider it to be a hack and do not use Lombok for this reason. That is understandable, but in my experience, Lombok’s productivity benefits outweigh any of these concerns. I have been happily using it for production projects for many years now.

Before going into details, I’d like to summarize the two reasons I especially value the use of Lombok in my projects:

  1. Lombok helps keep my code clean, concise, and to the point. I find my Lombok annotated classes very expressive and I generally find annotated code to be quite intention-revealing, though not everyone on the internet necessarily agrees.
  2. When I’m starting a project and thinking of a domain model, I tend to begin by writing classes that are very much a work in progress and that I change iteratively as I think further and refine them. In these early stages, Lombok helps me move faster by not needing to move around or transform the boilerplate code it generates for me.
Bean Pattern and Common Object Methods

Many of the Java tools and frameworks we use rely on the Bean Pattern. Java Beans are serializable classes that have a default zero-args constructor (and possibly other versions) and expose their state via getters and setters, typically backed by private fields. We write lots of these, for example when working with JPA or serialization frameworks such as JAXB or Jackson.

Consider this User bean that holds up to five attributes (properties), for which we’d like to have an additional constructor for all attributes, meaningful string representation, and define equality/hashing in terms of its email field:
Write Fat-free Java Code with Project Lombok - Image 2

For brevity here, rather than including the actual implementation of all the methods, I instead just provided comments listing the methods and the number of lines of code that the actual implementations took. That boilerplate code would have totalled more than 90% of the code for this class!

Moreover, if I later wanted to, say, change email to emailAddress or have registrationTs be a Date instead of an Instant then I’d need to devote time (with the help of my IDE for some cases, admittedly) to change things like get/set method names and types, modify my utility constructor, and so on. Again, priceless time for something that brings no practical business value to my code.

Let’s see how Lombok can help here:
8
Write Fat-free Java Code with Project Lombok - Image 3
Voilà! I just added a bunch of lombok.* annotations and achieved just what I wanted. The listing above is exactly all the code I need to write for this. Lombok is hooking into my compiler process and generated everything for me (see the screenshot below of my IDE).
1
Write Fat-free Java Code with Project Lombok - Image 4

As you notice, the NetBeans inspector (and this will happen regardless of IDE) does detect the compiled class bytecode, including the additions Lombok brought into the process. What happened here is quite straightforward:

  • Using @Getter and@Setter I instructed Lombok to generate getters and setters for all attributes. This is because I used the annotations at a class level. If I wanted to selectively specify what to generate for which attributes, I could have annotated the fields themselves.
  • Thanks to @NoArgsConstructorand@AllArgsConstructor, I got a default empty constructor for my class as well as an additional one for all the attributes.
  • The @ToString annotation auto-generates a handy toString() method, showing by default all class attributes prefixed by their name.
  • Finally, to have the pair ofequals()andhashCode() methods defined in terms of the email field I used @EqualsAndHashCode and parameterized it with the list of relevant fields (just the email in this case).
9
Customizing Lombok Annotations

Let’s now use some Lombok customizations following this same example:

  • I’d like to lower the visibility of the default constructor. Because I only need it for bean compliancy reasons, I expect consumers of the class to only call the constructor that takes all fields. To enforce this, I am customizing the generated constructor with AccessLevel.PACKAGE.
  • I want to ensure that my fields never get assigned null values, neither via the constructor nor via the setter methods. Annotating class attributes with @NonNull is enough; Lombok will generate null checks throwing NullPointerException when appropriate in the constructor and setter methods.
  • I’ll add a password attribute, but do not want it shown when calling toString() for security reasons. This is accomplished via the excludes argument of @ToString.
  • I’m OK exposing state publicly via getters, but would prefer to restrict outside mutability. So I am leaving @Getter as is, but again using AccessLevel.PROTECTED for @Setter.
  • Perhaps I would like to force some constraint on the email field so that, if it gets modified, some kind of check is run. For this, I just implement the setEmail() method myself. Lombok will just omit generation for a method that already exists.
This is how the User class will then look:
Write Fat-free Java Code with Project Lombok - Image 5

Note that, for some annotations, we are specifying class attributes as plain strings. Not a problem, because Lombok will throw a compile error if we, for example, mistype or refer to a non-existing field. With Lombok, we’re safe.

Also, just like for thesetEmail()method, Lombok will just be OK and not generate anything for a method the programmer has already implemented. This applies to all methods and constructors.
1
Immutable Data Structures

Another use case where Lombok excels is when creating immutable data structures. These are usually referred to as value types. Some languages have built-in support for these, and there’s even a proposal for incorporating this into future Java versions.

Suppose we want to model a response to a user login action. This is the kind of object we’d want to just instantiate and return to other layers of the application (for example, to be JSON serialized as the body of an HTTP response). Such a LoginResponse would not need to be mutable at all and Lombok can help describe this succinctly. Sure, there are many other use cases for immutable data structures (they’re multithreading- and cache-friendly, among other qualities), but let’s stick to this simple example:
Write Fat-free Java Code with Project Lombok - Image 6

Worth noting here:

  • A @RequiredArgsConstructor annotation has been introduced. Aptly named, what it does is generate a constructor for all final fields that have not already been initialized.
  • In cases where we want to reuse a previously issued LoginResonse (imagine, for example, a refresh token operation), we certainly don’t want to modify our existing instance, but rather, we want to generate a new one based on it. See how the @Wither annotation helps us here: It tells Lombok to generate a withTokenExpiryTs(Instant tokenExpiryTs) method that creates a new instance of LoginResponse having all the with’ed instance values, except the new one we’re specifying. Would you like this behavior for all fields? Just add @Wither to the class declaration instead.
4
@Data and @Value

Both use cases discussed so far are so common that Lombok ships a couple of annotations to make them even shorter: Annotating a class with @Data will trigger Lombok to behave just as if it had been annotated with @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor. Likewise, using @Value will turn your class into an immutable (and final) one, also again as if it had been annotated with the list above.

3
Builder Pattern

Going back to our User example, if we want to create a new instance, we’ll need to use a constructor with up to six arguments. This is already a rather large number, which will get even worse if we further add attributes to the class. Also suppose we’d want to set some default values for the lastNameandpayingCustomer fields.

Lombok implements a very powerful@Builderfeature, allowing us to use a Builder Pattern to create new instances. Let’s add it to our User class:
4
Write Fat-free Java Code with Project Lombok - Image 7
Delegation/Composition

If you want to follow the very sane rule of favor composition over inheritance that’s something Java does not really help with, verbosity wise. If you want to compose objects, you’d typically need to write delegating method calls all over the place.

Lombok proposes a solution for this via @Delegate. Let’s take a look at an example.

Imagine that we want to introduce a new concept ofContactInformation. This is some information ourUserhas and we may want other classes to have too. We can then model this via an interface like this:
3
Write Fat-free Java Code with Project Lombok - Image 8
Write Fat-free Java Code with Project Lombok - Image 9
Checked Exceptions

As we all know, Java differentiates between checked and unchecked exceptions. This is a traditional source forcontroversy and criticism to the language as exception handling sometimes gets too much in our way as a result, especially when dealing with APIs designed to throw checked exceptions and therefore forcing us developers to either catch them or declare our methods to throw them.

1
Write Fat-free Java Code with Project Lombok - Image 10
Logging
Write Fat-free Java Code with Project Lombok - Image 11
Annotating Generated Code

If we use Lombok to generate code, it may seem we’d lose the ability to annotate those methods since we’re not actually writing them. But this is not really true. Rather, Lombok allows us to tell it how we’d want generated code to be annotated, using a somewhat peculiar notation though, truth be told.

Consider this example, targeting the use of a dependency injection framework: We have a UserService class that uses constructor injection to get the references to a UserRepository andUserApiClient.
2
Write Fat-free Java Code with Project Lombok - Image 12
Learning More

The Lombok usage explained in this post focuses on those features that I have personally found to be most useful over the years. However, there are many other features and customizations, available.

Lombok’s documentation is very informative and thorough. They have dedicated pages for every single feature (annotation) with very detailed explanations and examples. If you find this post interesting, I encourage you to dive deeper into lombok and its documentation to find out more.

The project site documents how to use Lombok in several different programming environments. In short, most popular IDEs (Eclipse, NetBeans and IntelliJ) are supported. I myself regularly switch from one to another on a per-project basis and use Lombok on all of them flawlessly.

2
Delombok!

Delombok is part of the Lombok toolchain and can come in very handy. What it does is basically generate the Java source code for your Lombok annotated code, performing the same operations the Lombok generated bytecode does.

This is a great option for people considering adopting Lombok but not quite sure yet. You may freely start using it and there’ll be no vendor lock-in. In case you or your team later regret the choice, you can always use delombok to generate the corresponding source code which you can then use without any remaining dependency on Lombok.

Delombok is also a great tool to learn exactly what Lombok will be doing. There are very easy ways to plug it into your build process.

1

There are many tools within the Java world that make a similar usage of annotation processors to enrich or modify your code at compile time, such as Immutables or Google Auto Value. These (and others, for sure!) overlap with Lombok feature-wise. I particularly like the Immutables approach a lot and have also used it in some projects.

It’s also worth noting that there are other great tools providing similar features for bytecode enhancing, such as Byte Buddy or Javassist. These typically work at runtimethough, and comprise a world of their own beyond the scope of this post.
2
Concise Java
There are a number of modern JVM targeted languages that provide more idiomatic—or even language level—design approaches helping address some of the same issues. Surely Groovy, Scala, and Kotlin are nice examples. But if you are working on a Java-only project, then Lombok is a nice tool to help your programs be more concise, expressive, and maintainable.
2
BY MIGUEL GARCÍA LÓPEZ

There are a number of tools and libraries I cannot imagine myself writing Java code without these days. Traditionally, things like Google Guava or Joda Time (at least for the pre Java 8 era) are among the dependencies that I end up throwing into my projects most of the time, regardless of the specific domain at hand.

Lombok surely deserves its place in my POMs or Gradle builds as well, albeit not being a typical library/framework utility. Lombok has been around for quite a while now (first released in 2009) and has matured a lot since. However, I have always felt it deserved more attention—it is an amazing way of dealing with Java’s natural verbosity.

In this post, we will explore what makes Lombok such a handy tool.

have a taste for humor—you cannot miss this intro they made at a past conference!

Let’s see how Lombok does its magic and some usage examples.

more than 90% of the code for this class!

Moreover, if I later wanted to, say, change email to emailAddress or have registrationTs be a Date instead of an Instant then I’d need to devote time (with the help of my IDE for some cases, admittedly) to change things like get/set method names and types, modify my utility constructor, and so on. Again, priceless time for something that brings no practical business value to my code.

Let’s see how Lombok can help here:

@Getter@Setter I instructed Lombok to generate getters and setters for all attributes. This is because I used the annotations at a class level. If I wanted to selectively specify what to generate for which attributes, I could have annotated the fields themselves.
  • Thanks @NoArgsConstructor@AllArgsConstructor I got a default empty constructor for my class as well as an additional one for all the attributes.
  • @ToString auto-generates a toString(), showing by default all class attributes prefixed by their name.
  • Finally, to have the equals()hashCode() defined in terms of the email field I @EqualsAndHashCode parameterized it with the list of relevant fields (just the email in this case).


  • setEmail(), Lombok will just be OK and not generate anything for a method the programmer has already implemented. This applies to all methods and constructors.

    @RequiredArgsConstructor annotation has been introduced. Aptly named, what it does is generate a constructor for all final fields that have not already been initialized.
  • In cases where we want to reuse a previously issued LoginResonse (imagine, for example, a refresh token operation), we certainly don’t want to modify our existing instance, but rather, we want to generate a new one based on it. See how @Wither helps us here: It tells Lombok to generate a withTokenExpiryTs(Instant tokenExpiryTs) method that creates a new instance of LoginResponse having all the instance values, except the new one we’re specifying. Would you like this behavior for all fields? Just @Wither the class declaration instead.


  • @Data trigger Lombok to behave just as if it had been annotated with @Getter + @Setter + @ToString + @EqualsAndHashCode @RequiredArgsConstructor Likewise, @Value turn your class into an immutable (and final) one, also again as if it had been annotated with the list above.

    suppose we’d want to set some default values for lastNamepayingCustomer.

    Lombok implements a very @Builder, allowing us to use a Builder Pattern to create new instances. Let’s add it to our User class:

    @Delegate Let’s take a look at an example.

    Imagine that we want to introduce a new concept ContactInformation This is some information User and we may want other classes to have too. We can then model this via an interface like this:

    controversy and criticism to the language as exception handling sometimes gets too much in our way as a result, especially when dealing with APIs designed to throw checked exceptions and therefore forcing us developers to either catch them or declare our methods to throw them.

    though, truth be told.

    Consider this example, targeting the use of a dependency injection framework: We have a UserService class that uses constructor injection to get the references to a UserRepository UserApiClient

    and its documentation to find out more.

    The project site documents how to use Lombok in several different programming environments. In short, most popular IDEs (Eclipse, and IntelliJ) are supported. I myself regularly switch from one to another on a per-project basis and use Lombok on all of them flawlessly.

    to generate the corresponding source code which you can then use without any remaining dependency on Lombok.

    Delombok is also a great tool to learn exactly what Lombok will be doing. There are very easy ways to plug it into your build process.

    and comprise a world of their own beyond the scope of this post.

    a number of modern languages that provide more idiomatic—or even language level—design approaches helping address some of the same issues. Surely Groovy, Scala, and Kotlin are nice examples. But if you are working on a Java-only project, then Lombok is a nice tool to help your programs be more concise, expressive, and maintainable.

    2

    Write Fat-free Java Code with Project Lombok - Image 13

    Write Fat-free Java Code with Project Lombok | Toptal

    https://www.toptal.com/java/write-fat-free-java-code-project-lombok

    Java has some idiosyncrasies of its own and design choices that can make it rather verbose. While Java is a mature and performant programming language, developers frequently need to write boilerplate code that bring little or no real value other than complying with some set of constraints and conventions. In this article, Toptal Freelance Software ...

    This blog is listed under Development & Implementations Community

    Related Posts:

    Java

     

    Lombok

     
    View Comment (1)
    Post a Comment

    Please notify me the replies via email.

    Important:
    • We hope the conversations that take place on MyTechLogy.com will be constructive and thought-provoking.
    • To ensure the quality of the discussion, our moderators may review/edit the comments for clarity and relevance.
    • Comments that are promotional, mean-spirited, or off-topic may be deleted per the moderators' judgment.
    1. 13 June 17
      0

      This is a very informative article. I also agree with your post title and your really well explain your point of view. I am very happy to see this post. Thanks for share with us. Keep it up and share the more most related post. thank you Easy to understand Programming http://www.codeverb.com/cpp-interview-questions

    You may also be interested in
    Awards & Accolades for MyTechLogy
    Winner of
    REDHERRING
    Top 100 Asia
    Finalist at SiTF Awards 2014 under the category Best Social & Community Product
    Finalist at HR Vendor of the Year 2015 Awards under the category Best Learning Management System
    Finalist at HR Vendor of the Year 2015 Awards under the category Best Talent Management Software
    Hidden Image Url

    Back to Top