Lombok – oder die Geschichte von dem, der auszog, Boilerplate Code zu vertreiben

Der Sprache Java wird häufig angelastet, bei der Definition von Klassen zu viel unnützen – „Boilerplate“ – Code zu benötigen. So werden fachliche Attribute i. A. in privaten Instanzvariablen abgelegt, für die dann öffentliche Getter und/oder Setter benötigt werden. Zudem sollte nahezu jede Klasse eine Implementierung der Methoden equals und hashCode besitzen. Und toString wäre auch ganz schön. Neben dem eigentlich wichtigen Inhalt einer Klasse muss also noch eine Menge Code geschrieben werden, der auch generiert werden könnte. Dies kann man natürlich mit Hilfe der gängigen IDEs tun, was aber nur bei der ersten Erstellung der Klassen hilft. Bei späteren Änderungen – Attribute kommen hinzu oder fallen weg, Attributtypen ändern sich – ist eine aufwändigere, meist mauelle Anpassung unumgänglich.

Hier bietet das Projekt Lombok eine andere Herangehensweise: Die Klassen werden durch Annotationen angereichert und ein Annotation Processor erzeugt den Code zur Build-Zeit. Die wesentlichen Annotationen sind diese:

  • @Getter, @Setter
    fügen zu einem Attribut eine Getter- bzw. Setter-Methode hinzu. Auf Klassenebene angewendet, werden die Methoden für alle Attribute erzeugt, die keine eigene Annotation besitzen.
  • @EqualsAndHashCode
    erzeugt die Methoden equals und hashCode auf Basis aller oder einzelner Attribute.
  • @Data
    entspricht @Getter @Setter @EqualsAndHashCode. Zusätzlich wird auch ein Konstruktor erzeugt.

Eine detailierte Beschreibung dieser Annotationen sowie weiterer Bestandteile von Lombok findet man hier.

Zur Einbindung in Maven-Projekte reicht es, die folgende Dependency aufzunehmen:

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.16.8</version>
</dependency>

Neben den zur Laufzeit benötigten Klassen enthält die Bibliothek auch den erwähnten Annotation Processor, der die Generierung des zusätzlichen Programmcodes übernimmt.

Eclipse benötigt zur Integration von Lombok einen Java-Agenten. Er kann der Eclipse-Konfiguration durch Ausführung des Lombok-JAR-Files hinzugefügt werden: java -jar lombok-1.18.8.jar. Das Tool findet ggf. installierte Eclipse-Versionen nicht selbstständig. In dem Fall muss man im angezeigten Dialog das Eclipse-Verzeichnis angeben, in dem sich die Konfigurationsdatei eclipse.ini befindet (bzw. jbdevstudio.ini beim JBoss Developer Studio). Welche Änderungen das Tool an der Eclipse-Installation vornehmen wird, kann man sich zunächst anzeigen lassen.
NetBeans benötigt keine besondere Einstellung für Lombok, soweit die bearbeiteten Projekte Maven-Projekte sind (s. o.).
Für IntelliJ gibt es ein Lombok-Plugin, das aktiviert werden muss.

Für einfache Fachobjekte eignet sich @Data recht gut. Damit werden Getter, Setter, equals, hashCode und toString auf Basis aller Attribute bereitgestellt (s. Beispiel aus der Lombok-Doku).

Für JPA-Entities ist @Data aber zu starr: Zum einen wird ein Standardkonstruktor (ohne Parameter) benötigt, zum anderen sollen equals und hashCode nur die Id-Attribute benutzen. Daher sollten statt @Data eher die einzelnen Annotationen @Getter etc. verwendet und die Attributliste für @EqualsAndHashCode auf die Id-Attribute eingeschränkt werden:

@Entity
@Getter
@Setter
@EqualsAndHashCode(of = "isoCode")
@ToString
public class Country
{
  @Id
  private String    isoCode;

Für Entity-Klassen mit generierter Id reicht aber auch das nicht, da equals bei noch nicht gesetzter Id (null) in min.einem der beiden verglichenen Objekte false zurückgeben sollte. Die von Lombok generierte Methode liefert aber true.

Best Practice bei GEDOPLAN ist es daher, Entity-Klassen von einer der von uns geschriebenen Basisklassen SingleIdEntity, StringIdEntity, GeneratedIntegerIdEntity etc. abzuleiten. equals, hashCode und toString sind dann in der Basisklasse bereits korrekt implementiert. Die Lombok-Annotationen @EqualsAndHashCode und @ToString sind dann nutzlos bzw. kontraproduktiv. @Getter und @Setter können aber sinnvoll eingesetzt werden:

@Entity
@Access(AccessType.FIELD)
@Getter
@Setter
public class City extends GeneratedIntegerIdEntity
{

Die erwähnten Basisklassen stammen aus unserer Bibliothek baselibs-persistence, die mit folgender Maven-Dependency einbezogen werden kann:

<dependency>
  <groupId>de.gedoplan</groupId>
  <artifactId>baselibs-persistence</artifactId>
  <version>1.0.30</version>
</dependency>

An gleicher Stelle liegen auch die Sourcen dieser Klassen, wenn Sie dort mal hineinschauen möchten.

In https://github.com/GEDOPLAN/lombok-demo steht ein Showcase zum Anschauen und Ausprobieren bereit.

Advertisements

Über Dirk Weil
Dirk Weil ist seit 1998 als Berater im Bereich Java tätig. Als Geschäftsführer der GEDOPLAN GmbH in Bielefeld ist er für die Konzeption und Realisierung von Informationssystemen auf Basis von Java EE verantwortlich. Seine langjährige Erfahrung in der Entwicklung anspruchsvoller Unternehmenslösungen machen ihn zu einem kompetenten Ansprechpartner und anerkannten Experten auf dem Gebiet Java EE. Er ist Autor in Fachmagazinen, hält Vorträge und leitet Seminare und Workshops aus einem eigenen Java-Curriculum.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: