Java Without the Boilerplate – Project Lombok
July 26th, 2010Project Lombok is a very cool little Java library that aims (and succeeds) in removing boilerplate, meaningless, and uninteresting code from your Java objects. The basic idea is to replace things like getters and setters with simple annotations, and then let the Java compiler generate the necessary bytecode in the .class file so that tools such as Eclipse and the Java compiler have no idea what anything unusual happened. Lombok hooks into the compiler to make sure this happens correctly.
First we’ll cover some Lombok basics and then show how it can be used with the Canoo RIA Suite (ULC) project and and view generators. This includes details on how to mix Lombok annotated objects with JPA annotations, which you might want to glance at before leaving!
Update: You do not need ULC to work with Lombok. The two are separate projects.
Lombok in Action
So let’s see Lombok in action. Consider this Java class that includes a Lombok annotation:
import lombok.Data;
public @Data class Contact {
private String name;
private String email;
private String primaryPhone;
}
OK, so there is an @Data annotation in there. So what? Well, to javac and tools (like Eclipse) this class has getters and setters for all three fields, an equals and hashcode implementation, and a toString method. Eclipse tools still give you autocomplete the Navigator shows the correct methods. Not only did you not have to write (or generate) the code yourself, but you don’t have to see that code when coming back in maintenance mode. The interesting bits of your class are no longer buried in the noise. Consider what this looks like without lombok:
public @Data class Contact {
private String name;
private String email;
private String primaryPhone;
public String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
void setEmail(String email) {
this.email = email;
}
public String getPrimaryPhone() {
return primaryPhone;
}
void setPrimaryPhone(String primaryPhone) {
this.primaryPhone = primaryPhone;
}
@Override public String toString() {
return "Contact(" + name + ", "
+ email + ", "
+ primaryPhone + ")";
}
@Override public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != this.getClass()) return false;
Contact other = (Contact) o;
if (name == null
? other.name != null
: !name.equals(other.name)) return false;
if (email == null
? other.email != null
: !email.equals(other.email)) return false;
if (primaryPhone == null
? other.primaryPhone != null
: !primaryPhone.equals(other.primaryPhone)) return false;
return true;
}
@Override public int hashCode() {
final int PRIME = 31;
int result = 1;
result = (result*PRIME) + (name == null
? 0
: name.hashCode());
result = (result*PRIME) + (email == null
? 0
: email.hashCode());
result = (result*PRIME) + (primaryPhone == null
? 0
: primaryPhone.hashCode());
return result;
}
That’s a lot of code for something so simple. It doesn’t even fit in my browser margins without funky line breaks! Sure, IDEs can generate it for you. But what if something interesting is buried in the equals() method? Or perhaps a setter has a side-effect? You can’t easily see this with the reams of boilerplate typical of Java. With lombok, only the essentials are displayed, so the unique parts of the object will stand out to the future reader. And yes, even using @Data you are free to provide your own implementations for any of these methods.
Richard Gabriel made this observation when comparing old programs (like MacPaint) to “modern” programs writen in langauges like Java:
I’m always delighted by the light touch and stillness of early programming languages. Not much text; a lot gets done. Old programs read like quite conversations between a well-spoken research worker and a well-studied mechanical colleague, not as a debate with a compiler. Who’d have guessed sophistication brought such noise.
Now, with Lombok, sophistication is finally taking the noise away, rather than adding to it.
Just a couple important details before moving on to a Lombok example that uses Canoo’s RIA Suite…
Lombok with Canoo RIA Suite
The point of this was to make sure I could use Lombok on my next RIA Suite(aka ULC) project. It’s looks like I can, and you can too. To prove it, let’s generate a RIA Suite project, add a domain class using Lombok, generate the views, and run the application.
Prerequisites
Steps
Here are the steps we’ll perform to get this thing working:
Generate the Project
The ULC Application Development Guide contains a 10 page getting started tutorial that walks you through the process from starting at zero and going to a deployed RIA Suite application. Really, it is quite simple. You just need to add the Project Generator as an external tool in Eclipse. Although it is a bunch of screenshots, this is a common task for Eclipse users and little can go wrong.
In Eclipse, click Run -> External Tools > Open External Tools Dialog… and point a new external tool to your “/addon/generators/build-setup.xml” from the RIA Suite install. Your window should look like this:

Now you’ll have the menu entry for Run -> External Tools -> ULC Project Generator, which you should click now. You’ll be prompted for a project name and whatnot, and a sample Contacts application will look like this:

The script runs and you now have a project on disk that can be run. Just click to File -> Import to import it, navigating to where it is on disk. Your import screen should look like this:

If it all goes well your project should be open and your Project Explorer should look like this:

Add the Lombok Jar
We need to add the lombok.jar to the Contacts project, add it to the build classpath, and click Refresh to make sure Eclipse is aware that something changed.
Copy the lombok.jar to ./Contacts/lib/development directory in your project. Then edit the project properties (right click the Contacts project and select Properties), select the Java Build Path entry, and add lombok.jar as a Jar. Should look like this:

Create Domain Object
Let’s add a domain object with JPA persistence to our project. A Contacts application must show a Contact, right? This looks about right:
package org.sample.contacts.domain;
import javax.persistence.*;
import lombok.*;
@Entity
public @Data class Contact {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private Long id;
private String name;
private String email;
private String primaryPhone;
}
Let me explain a few details… The class is marked @Entity so that JPA persistence works. The class will map to a Contact table in the database. The class is marked @Data so that lombok will weave in getters, setters, toString, equals, and hashcode methods. The @Id annotation on the “id” field marks that field as the primary key to JPA, and the @GeneratedValue means the field auto increments. I use the GenerationType.SEQUENCE strategy because I plan on deploying to Google App Engine, otherwise this parameter here is unneeded. Lastly, getters and setters are supressed on the id field by adding @Getter(AccessLevel.NONE) and @Setter(AccessLevel.NONE). If you don’t do this then the view-layer automation of Ria Suite is going to, by default, provide you with edit fields for the id, which you should not do.
Generate the View Layer
To generate the view layer, click Run -> External Tools -> “Contacts generate-beans-view”. This tool was installed for you by the Project Generator. Running it generates a simple Create-Read-Update-Delete (CRUD) interface with a table, buttons, and entry editor. You’ll see a couple new classes and property files in your application after you run the tool.
Run application
Last thing to do is run the app. Click Run -> Run History -> Contacts (again installed by the project generator), sit back, and behold an application.

That’s it!
Next step is to deploy to Google App Engine using that Contacts-copy-to-GoogleApp tool that the generator installed, but that is a blog post (and task) for another day.
Enjoy!
Posted by Hamlet


