Vaadin auf Grails: Kann das funktionieren?

Projektanfragen mit dem Wunsch, eine Rich Internet Application auf Basis des bekannten Vaadin-Frameworks zu entwickeln oder zu erweitern, sind für uns als Vaadin-zertifizierter Partner mittlerweile zur Selbstverständlichkeit geworden. Bei den meisten Kunden ist dabei bereits eine bestehende JEE-Architektur vorhanden, in welche das Vaadin-Framework eingebettet werden soll. Im Gegensatz dazu unterstützen wir aktuell einen Verlag bei einem agilen „Green-Field-Projekt“: einer vollkommenen Neuimplementierung einer Rich Internet Application mit Vaadin. Die Besonderheit dieses Projekts liegt darin, dass statt einer herkömmlichen JEE-Umgebung eine ebenfalls neu zu entwickelnde Grails-Architektur als Backend dienen soll.

Dieser Blog-Post soll nun einen kurzen Überblick über das Zusammenspiel der beiden Web-Frameworks geben.

Auf eine Beschreibung von Vaadin möchte ich an dieser Stelle verzichten; sie lässt sich in unserer Vaadin-Leistungsbeschreibung nachlesen. Allerdings sei an dieser Stelle ganz kurz auf Grails eingegangen:

Grails

Grails ist ein JVM Full-Stack Webframework für die dynamische Skriptsprache Groovy, das von dem bekannten Ruby-On-Rails Framework inspiriert ist. „Full-Stack“ bedeutet, dass alle nötigen Technologien für das Erstellen von Web-Applikationen bereits im Framework integriert und vorkonfiguriert sind. Bei Grails sind das beispielsweise Spring als Dependency Injection Container, Hibernate als OR-Mapper und Quartz als Task-Scheduler.
Wie Ruby-On-Railsverfolgt Grails einen „Convention-over-Configuration“–Ansatz. Dadurch entfällt eine umfangreiche manuelle Konfiguration der zugrundeliegenden Technologien durch XML-Dateien oder Annotationen. Dies soll Entwicklern den Einstieg erleichtern und sehr schnell zu produktivem Code führen.

Das Vaadin-Plugin für Grails

Um die Integration eines Vaadin-Frontends in ein Grails-Backend möglichst einfach zu gestalten, hat die Community das Vaadin-Plugin für Grails unter der Apache License 2.0 kostenfrei zur Verfügung gestellt.
Neben dem initialen Setup eines Projekts wird durch das Plugin insbesondere die Verwendung von Springs Dependency Injection sowie die Internationalisierung von Texten in Vaadin-Klassen deutlich erleichtert.
Für das Setup eines Vaadin-Projekts in Grails auf Basis von IntelliJ IDEA verweise ich an dieser Stelle auf ein englischsprachiges Tutorial im Vaadin-Wiki. Anleitungen für Eclipse und Netbeans finden sich in [1].

Dependency Injection

Wie von Spring bereits bekannt, lassen sich auch in Grails Service-Instanzen über eine Spring-Annotation automatisch injizieren:

class MyService {

   @Autowired
   MyOtherService otherServiceInstance

   // some great code following
}

Durch den bereits erwähnten „Convention-over-Configuration“-Ansatz kann auf diese Spring-Annotation allerdings auch verzichtet werden, indem man die Service-Instanz analog zur Service-Klasse benamt, wie in folgendem Beispiel zu sehen ist:

class MyService {

   MyOtherService myOtherService

   // some great code following…
}

In Vaadin-Klassen funktioniert dieser Mechanismus leider nicht, da Vaadin den Lebenszyklus seiner Objekte selbst steuert und dadurch sozusagen „an Spring vorbei arbeitet“. Spring ist sich also der Existenz der Vaadin-Instanzen nicht „bewusst“ und kann dementsprechend auch keine Mehrwertdienste à la Dependency Injection liefern. Genau hier schafft das Vaadin-Plugin für Grails Abhilfe und bedient sich eines gängigen Tricks in Spring-Applikationen: Über einen simplen statischen Aufruf auf die Klasse „Grails“ wird der Service dynamisch aus dem Spring-Application-Context gezogen und kann wie gewohnt benutzt werden.

class MyService {

   MyOtherService myOtherService = Grails.get(MyOtherService)

   // some great code following…
}

Internationalisierung

Auch für die Darstellung von Text in unterschiedlichen Sprachen wird auf Spring zurückgegriffen – genauer gesagt auf Springs MessageSource. Über einen statischen Methodenaufruf auf die schon bekannte „Grails“-Klasse erhält man Strings für unterschiedliche Locales. Voraussetzung ist natürlich, dass Ressource-Dateien für die gewünschten Locales erstellt und befüllt wurden. Durch ein Überladen der i18n()-Methode werden alle benötigten Use-Cases adressiert, wie im Folgenden zu sehen ist:

// default locale
String title = Grails.i18n(“title”)

// german locale
String title = Grails.i18n(“title”, Locale.DE)

// default locale with parameter
String subTitle = Grails.i18n(“subTitle”, 42)

// german locale with parameter
String subTitle = Grails.i18n(“subTitle”, [42] as Object[], Locale.DE)

Groovy-Closures

Das Feature, das ich nun vorstellen möchte, kann unabhängig von dem bereits beschriebenen Vaadin-Plugin für Grails eingesetzt werden: Groovy-Closures. Jeder Entwickler, der schon einmal mit Vaadin oder einem anderen UI-Framework unter Java 6/7 gearbeitet hat, kennt die Problematik: Um einen einfachen ClickListener auf einen Button zu legen, ist einiges an Boilerplate-Code nötig, beispielsweise über eine Anonyme Innere Klasse:

Button button = new Button("Click me");
button.addClickListener(new Button.ClickListener() {
     @Override     
     void buttonClick(Button.ClickEvent clickEvent) {         
          Notification.show(String.format("'%s' was clicked", clickEvent.getButton().getCaption()));
     }
});

Durch den Einsatz von Groovy-Closures kann dieselbe Funktionalität mit deutlich weniger Aufwand realisiert werden:

Button button = new Button("Click me")
button.addClickListener() {Button.ClickEvent clickEvent ->
    Notification.show("'${clickEvent.button.caption}' was clicked")
}

Falls auf den „clickEvent“-Parameter nicht zugegriffen werden muss, geht es sogar noch einfacher:

Button button = new Button("Click me")
button.addClickListener() {
    Notification.show("A button was clicked")
}

Dies war nur eine äußerst kurze Vorstellung von Groovy-Closures und deren Verknüpfung mit Vaadin. Über viele weitere interessante Anwendungsfälle ließe sich problemlos ein separater Blog-Post verfassen.

Fazit

Natürlich gibt es neben den hier exemplarisch beschriebenen Features noch sehr viele weitere, die ein Grails-Backend bieten kann, wie beispielsweise das „Grails Object Relational Mapping“ (GORM). Auch sind diese selbstverständlich nicht allein auf Vaadin-Applikationen beschränkt, sondern lassen sich auch in Kombination mit anderen oder gänzlich ohne weitere Frontend-Frameworks einsetzen.
Nichtsdestotrotz konnten wir in eingangs erwähntem agilen „Green-Field-Projekt“  durch das harmonische Zusammenspiel von Vaadin, Grails sowie dem Vaadin-Plugin für Grails unglaublich schnell produktiven Code entwickeln und auch releasen. Dies ermöglichte uns, das für die agile Produktentwicklung so wichtige frühe Feedback sehr schnell einzuholen und in die folgenden Iterationen einzuarbeiten, was wesentlich zum Projekterfolg beigetragen hat.

Quellen/Links:

  1. Ondrej Kvasnovsky: Vaadin on Grails - Rapid development of Rich Internet Applications with Vaadin and Grails.
  2. Jaroslav Holan, Ondrej Kvasnovsky: Vaadin 7 Cookbook
  3. https://vaadin.com/
  4. https://grails.org/
  5. http://www.groovy-lang.org/
  6. https://grails.org/plugin/vaadin
  7. http://vaadinongrails.com