Tired of Getters and Setters? Lombok them!

Markus Eisele
6
I love Java. There is a lot of amazing stuff being build with it every minute and I really love being part of that community. But, to be honest, there is one single thing, that I hate. That is the JavaBeans™ architecture.
Not completely but the basic requirements to have a nullary constructor and property access using getter and setter methods. All this is stupid overhead, hard to maintain and change. But there is a little helper out there, that made my life more easier. It's project Lombok. Here is a very short overview about using Lombok with ManagedBeans.

Getting Started

Grep your favorite IDE (Eclipse/NetBeans) and start your new Maven based Java EE 6 web-project. Add the Lombok dependency to your pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>0.10.0</version>
<scope>compile</scope>
</dependency>
And you are done. If you are not using Maven, get your copy of the lombok.jar from the project's website. That's all. Your done.

Coding the ManagedBean with Lombok

Create a new class named "Customer" and add some String fields: public class Customer {
private String name;
private String sure_name;
private String nickname;
}
But what happens if you try to use this one as @ApplicationScoped @ManagedBean? For sure your JSF runtime will complain about missing properties and constructors. But instead of adding all those boilerplate code you simply add @Data as an additional annotation to your class which should look like this now: @ManagedBean
@ApplicationScoped
@Data
public class Customer {
private String name;
private String surename;
private String nickname;
}
Now get a simple JSF frontend and add some: <h:inputText id="name" value="#{customer.name}" /> for every field in your bean to it and you are done. Everything works. And nobody is complaining about missing properties anymore!

What happened?
The offered Lombok annotation @Data simply tells your IDE to generate all the boilerplate code for you silently. And this is done during compile time, so you usually don't have to care about lombok being on your runtime path at all. There are some exceptions to this rule with other Lombok features but it's true for this simple example. @Data especially is a convenient shortcut annotation that bundles the features of @ToString, @EqualsAndHashCode, @Getter / @Setter and @RequiredArgsConstructor together: In other words, @Data generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate toString, equals and hashCode implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with @NonNull or @NotNull, in order to ensure the field is never null. If you look at the generated source you see that the compiled file is there and contains all your well known boilerplate:
>javap Customer
Compiled from "Customer.java"
public class net.eisele.lombokdemo.Customer {
public java.lang.String process();
public net.eisele.lombok_jsf.Customer();
public java.lang.String getName();
public java.lang.String getSurename();
public java.lang.String getNickname();
public void setName(java.lang.String);
public void setSurename(java.lang.String);
public void setNickname(java.lang.String);
public boolean equals(java.lang.Object);
public boolean canEqual(java.lang.Object);
public int hashCode();
public java.lang.String toString();
}

That's all?
Not really :) There are some more features Lombok has to offer. e.g. a simple @Log which gives you access to a private static final java.util.logging.Logger log
field to simply log what's happening. You can also have a @Log4j, @CommonsLog or even a @Slf4j as alternatives. If you are looking for all the goddess, look at the project's feature overview page.

Risks?
One could argue that having all those fancy stuff done by a compiler could lead to unexpected results and probably introduces errors nobody likes. Right. But even if you don't like all those automated and transparent generation, you could simply Delombok your source files. This would simply replace all lombok annotations with the generated code and gives your access to a complete codebase. So it's a calculable risk using Lombok and I must admit: I love it.

Post a Comment

6Comments

  1. Lombok has severe problems with Eclipse format save-actions. If I have to decide between Lombok and Autoformat I go for the Autoformat in big teams. It's important for code repositories.

    @Data (contains @ToString etc.) might sound fantastic on paper, escpecially for Entities, but we don't use this. Data/ToString/Hash tries to read all attributes and before you can say moo you will load half the database and trigger all kind of nasty LazyInitExceptions.

    Really - use it just a month in practice and you will be very tempted to kick this stuff out of your project.
    We only use Getter/Setter now with special Eclipse settings and I consider to delete even that.

    ReplyDelete
  2. André,

    thanks for your comment. You have to use it carefully, of course. As with any other "magic" happening. Thanks for sharing your experiences.

    - M

    ReplyDelete
  3. Quite simply, doesn't work at all.

    /pages/index.xhtml @12,63 value="#{signin.username}": Target Unreachable, identifier 'signin' resolved to null

    Doesn't see the username param at all without the getter/setter

    ReplyDelete
    Replies
    1. Hi Keith,

      Sounds as if your project isn't setup the right way.
      You might use the wrong @Data import?

      -m

      Delete
  4. Hi Markus,

    That error is slightly out dated it changed a couple hours later with some changes to my Bean.

    I now have:

    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.RequestScoped;

    import lombok.Data;
    import lombok.Getter;
    import lombok.Setter;

    @ManagedBean(name="signin")
    @RequestScoped
    @Data
    public class SigninFace implements Serializable {

    private Integer id;
    private String username;
    private String password;
    }

    XHTML


    And now in my XHTML I'm getting

    /pages/index.xhtml @12,59 value="#{signin.username}": Property 'username' not found on type com.projects.jsf.SigninFace

    ReplyDelete
  5. Sorted!!!!

    Sorry guys, but from what I can see, there's no mention of this here:-

    http://stackoverflow.com/questions/3418865/cannot-make-project-lombok-work-on-eclipse-helios

    Running java -jar lombok.jar under the location of the lombok.jar 'installs' lombok on Eclipse and now it seems to have worked!

    ReplyDelete
Post a Comment