Spielerisch zum Ziel

Webanwendungen mit dem Java-Framework Play!

Timo Haberkern

Webframeworks für Java gibt es wie Sand am Meer. Mit Play! hat sich vor Kurzem ein weiteres in die lange Liste eingetragen. Im Vergleich zu anderen Frameworks macht Play! vieles anders. Effizienz, Geschwindigkeit und schnelle Entwicklungszeiten werden hier großgeschrieben.

Für nahezu jede Programmiersprache existiert heute mindestens ein Webframework im Stile von Ruby on Rails, das verspricht, besonders effizient und produktiv zu sein. Rapid Application Development ist das Schlagwort der letzten Jahre. Erstaunlicherweise hat es ausgerechnet im Java-Lager lange gedauert, bis ein solches Framework zur Verfügung stand. Zwar existieren dort bereits seit Jahren sehr leistungsstarke Lösungen, die funktional zwar sehr mächtig sind, im Gegenzug jedoch dazu führen, dass die Produktivität durch zu viel Quellcode und Konfigurationsarbeiten leidet. Nicht umsonst eilt der Entwicklung von Webanwendungen mit Java der Ruf voraus, schwerfällig und zeitraubend zu sein und seine Vorteile erst in sehr großen Projekten auszuspielen. Einige Webframeworks schicken sich an, diesen Umstand zu ändern. Das im Folgenden vorgestellte Play! ist eines von ihnen.

Abb. 1: Das Play!-Framework verspricht eine besonders effektive und schnelle Webanwendungsentwicklung.

Das erklärte Ziel der Play!-Entwickler ist es, ein schnelles und schlankes Framework zu entwickeln, wobei sich schnell sowohl auf die Ablaufgeschwindigkeit als auch auf die Entwicklungseffizienz bezieht. Das Framework versucht hier den Spagat zwischen mehreren Welten. Zum einen versucht es die Einfachheit und Effizienz von Hype-Frameworks wie Rails oder Django und Scripting-Sprachen wie Ruby zu erzielen und zum anderen Java, mit seinen Vorteilen gegenüber nicht typisierten Skriptsprachen, als Plattform und Sprache zu nutzen. Dies gelingt auch gut. Bewährte Java-Bibliotheken wie HibernateLucene, Quarz und andere werden hinter einer einfachen und schnell erlernbaren Fassade versteckt. Play! kümmert sich um die meisten lästigen Arbeiten, sodass mehr Zeit für das Wesentliche während der Entwicklung bleibt.

[ header = Seite 2: Erste Schritte ]

Erste Schritte

Die Installation des Play!-Frameworks ist mit geringem Aufwand verbunden, sie beschränkt sich auf das Entpacken der Downloadversion auf dem lokalen Entwicklungssystem. Neben einem aktuellen JDK (Version 5 oder neuer) wird auf Entwicklerrechnern auch Python benötigt. Unix und MAC-OSX-Anwender haben dies in der Regel standardmäßig installiert. Für Windows-Benutzer sind die Python-Runtime-Programme bereits im Frameworkdownload enthalten. Nach dem Hinzufügen des Installationsverzeichnisses zur Pfad-Umgebungsvariablen ist alles für den ersten Einsatz vorgebreitet.

Play! ist ein so genanntes MVC-Framework. Hinter diesem Kürzel verbirgt sich das Model-View-Controller-Entwurfsmuster. Der Grundgedanke hinter diesem Pattern ist die strikte Trennung zwischen den Aufgabenbereichen einer Anwendung. Folgende Bereiche lassen sich hierbei unterscheiden:

  • Model: In der Model-Schicht ist die Datenlogik einer Anwendung untergebracht. Alle Klassen, die für den Zugriff auf Daten einer Datenbank verantwortlich sind, werden dieser Schicht zugeordnet.
  • View: Die Anzeigelogik einer Anwendung gehört zur View-Schicht. Play! unterstützt die Ausgabe von Webseiten durch diverse Tags, die ganze HTML-Konstrukte erzeugen können.
  • Controller: Diese Schicht ist das Bindeglied zwischen den beiden anderen Schichten. In einem Controller ist die Steuerungslogik zusammengefasst. In der Regel veranlasst der Controller, dass Daten durch die Model-Klassen aus der Datenbank gelesen werden, und gibt diese an die View-Schicht zur Anzeige weiter.

In Abbildung 2 werden die Zusammenhänge zwischen den einzelnen Schichten in grafischer Form dargestellt. Diese Art der Trennung von Aufgaben einer Anwendung in einzelne, voneinander unabhängige Teile hat mehrere Vorteile. So steigen dadurch beispielsweise die Übersichtlichkeit und damit auch die Wartungsfreundlichkeit des Quellcodes. Des Weiteren ist es einfacher, einzelne Bereiche durch neue Implementierungen auszutauschen. Wenn beispielsweise die Daten nicht mehr aus einer Datenbank, sondern per Webservice geladen werden sollen, genügt es in der Regel, die Model-Klassen anzupassen, die Controller-Klassen und die View-Bereiche bleiben in der Regel unberührt.

Welcher Controller aufgerufen wird, entscheidet das Framework selbstständig anhand des aufgerufenen URLs. Hierfür ist der so genannte Dispatcher verantwortlich, der aufgrund definierter Routing-Regeln automatisch zum passenden Controller weiterleitet. Eine Anwendung besteht somit aus mehreren Controller-Klassen.

Abbildung 2: Play! basiert auf dem MVC-Pattern zur Separierung der einzelnen Anwendungsteile

[ header = Seite 3: Alles hört auf mein Kommando ]

Alles hört auf mein Kommando

Wie bei vielen anderen modernen Webframeworks, spielt auch bei Play! während der Entwicklung die Kommandozeile eine wichtige Rolle. Über sie werden viele Aufgaben automatisiert und dadurch erheblich vereinfacht. Das Play!-Kommandozeilentool ist in Python entwickelt und begleitet Entwickler vom Start bis zum Deployment einer Anwendung. So wird beispielsweise durch den Aufruf des folgenden Kommandozeilenbefehls ein komplettes Programmgerüst angelegt: $> play new anwendungsname.

Nach Eingabe eines Projektnamens startet der Play-Projektgenerator. Das Ergebnis ist eine Verzeichnisstruktur, die in Abbildung 3 zu sehen ist. Im Projektverzeichnis befinden sich anschließend automatisch generierte Dateien für die Konfiguration, Front Controller und die gesamte Verzeichnisstruktur der Anwendung. Dieser Grundaufbau ist allen Play!-Anwendungen gemeinsam.

Abbildung 3: Die Struktur einer Play!-Anwendung wird automatisch generiert.

Abbildung 4: Viele komplexe Aufgaben lassen sich einfach per Kommandozeilenbefehl erledigen.

[ header = Seite 4: Entwicklungsumgebung ]

Entwicklungsumgebung

Play! setzt erfreulich wenig Infrastruktur auf einem Entwicklungssystem voraus. Ein Webserver wird nicht benötigt, Play! bringt hier bereits alles mit, was für den Entwickleralltag gebraucht wird. Das bereits vorgestellte run-Kommando startet die jeweilige Anwendung mit dem integrierten Webserver: $> play run.

Nach dem Ausführen des run-Befehls kann die Anwendung im Browser gestartet werden. Neu erzeugte Anwendungen liefern bereits ein Ergebnis, auch wenn sich dies auf eine Begrüßungsseite von Play! beschränkt. Bleibt die Wahl der Entwicklungsumgebung. Das Framework bringt hier in der aktuellen Version 1.0 Support für Eclipse und Netbeans mit. Dieser beschränkt sich allerdings im Moment darauf, kompatible Projektdateien zu erzeugen, die mit der jeweiligen IDE geöffnet werden können.

$> play netbeansify
$> play eclipsify

In beiden IDEs kann die Anwendung gestartet und auch debugged werden. Dazu wird automatisch der vom Framework mitgelieferte Webserver gestartet. Das Ganze geht ohne umständliches Deployment vonstatten. Ebenso verhält es sich während der Entwicklung. Änderungen an Dateien werden sofort erkannt und folgedessen beim nächsten Reload der Seite gleich geändert dargestellt. Ein Neustart der Anwendung oder ein Deployment ist nicht notwendig. Das Kompilieren der Änderungen im Hintergrund geschieht in der Regel so schnell, dass keinerlei Wartezeiten entstehen.

Abb. 5: Play! erzeugt auf Wunsch Projekte für gängige IDEs wie Eclipse oder Netbeans

Ein Plug-in für Eclipse ist bereits in Arbeit , zum Zeitpunkt der Artikelentstehung war es allerdings noch in keinem sinnvoll nutzbaren Zustand. In Arbeit sind dort beispielsweise verschiedene Wizards zur Erstellung von Controller- und Model-Klassen. Für Textmate existiert ein Bundle, das einige sinnvolle Aktionen mitbringt.

Model

Das Rückgrat der meisten Webanwendungen bildet meist eine Datenbank. Der Zugriff auf die Datenbankinhalte stellt somit mit den wichtigsten Teil eines Webframeworks dar. Je nach Größe und Umfang der Datenbank ist die Programmierung dieser Klassen eine Menge Arbeit. Play! setzt hier auf JPA bzw. Hibernate zur Realisierung des Zugriffs, allerdings aufgebohrt und erweitert um eine Komfortschicht. Dadurch wird der Umgang mit Datenbanken zum Kinderspiel, da nur noch wenig Programmierung oder Konfiguration notwendig wird. Die Entwicklung einer Model-Klasse unterscheidet sich nur geringfügig von einer „normalen“ JPA-Klasse. Wie im folgenden Listing zu sehen ist, kommen auch hier Annotationen zum Einsatz. Per Konvention werden alle Model-Klassen im Package app.models angelegt.

package models;

import java.util.*;
import javax.persistence.*;
import play.db.jpa.*;

@Entity
public class User extends Model {
public String email;
public String password;
public String fullname;
public boolean isAdmin;

public User(String email, String password, String fullname) {
this.email = email;
this.password = password;
this.fullname = fullname;
}
}

Der Unterschied zu einer JPA-Klasse liegt unter anderem an der Superklasse Model, die vom Play!-Framework zur Verfügung gestellt wird. Diese übernimmt beispielsweise auch die automatische Erzeugung einer nummerischen ID. Wem sich beim Anblick der public-Properties die Zehennägel aufrollen, dem sei an dieser Stelle versichert, dass das Play!-Framework sich in entsprechender Weise darum kümmert und für jedes Property automatisch Getter– und Setter-Funktionen zur Verfügung stellt, um auf die Daten zuzugreifen.

Ganz nebenbei kümmert sich das Play-Framework um Dinge wie die Erstellung der Datenbanktabellen, falls diese bei neu angelegten Klassen noch nicht zur Verfügung stehen. Auch um das Handling der Datenbank-Connection und Session-Handler kümmert sich Play! automatisch. Funktional können alle Features von JPA genutzt werden. Relationen und LOBs sind natürlich ebenso möglich wie die Abfrage der Daten über Finder-Methoden oder die Validierung der Daten vor dem Schreiben in die Datenbank.

[ header = Seite 5: View, CRUD, Werkzeugkasten & Fazit ]

View

Der Zugriff auf eine Datenquelle ist natürlich nur die halbe Miete. Die gelesenen Informationen müssen dem Benutzer auch aufbereitet dargestellt werden. Play! bietet hierzu eine Template Engine, in der Groovy als Expression Language genutzt werden kann, um HTML, XML, JSON oder jedes andere textbasierte Ausgabeformat zu erzeugen. Durch die Verwendung von Groovy können dynamische Teile kompakt und übersichtlich dargestellt werden. Neben den normalen Sprachmitteln von Groovy können auch Tags verwendet werden, die beispielsweise die Erstellung von Links übernehmen. Solche Tags lassen sich natürlich auch sehr einfach selbst erstellen.

CRUD

Zwar ist die Erstellung von Views durch die eingebauten Funktionen von Play! einfach und geht leicht von der Hand, dennoch wird man oft feststellen, dass man häufig Masken implementiert, die die vier Grundoperationen auf einen Datenbestand abdecken. Die Rede ist hier von den so genannten CRUD-Operationen (Create, Retrieve, Update und Delete). Diese Operationen werden in der Regel für den Großteil der Model-Klassen implementiert. Dabei unterscheiden sich die Masken häufig nur durch die Felder, die für die jeweilige Klasse erfasst werden müssen. Die Arbeit ähnelt sich also von Maske zu Maske.

Daher liegt es nahe, die Erstellung der Masken für die CRUD-Operationen zu automatisieren. Play! bringt genau hierzu Werkzeuge mit, welche die Seiten für die CRUD-Operationen erzeugen können. Für die Erstellung von CRUD-Masken genügt es, einen entsprechenden Controller zu implementieren. Per Konvention muss die Benennung der Controller-Klasse die Mehrzahl der zugeordneten Model-Klasse sein. Das folgende Beispiel zeigt einen CRUD-Controller für die Model-Klasse User.

package controllers;

import play.*;
import play.mvc.*;

public class Users extends CRUD {
}

Über verschiedene Annotationen kann beispielsweise Einfluss darauf genommen werden, welche Felder der Model-Klassen wie dargestellt werden. Wer mehr Einfluss auf das Aussehen der Masken benötigt, kann die Templates dazu auch selbst definieren.

Werkzeugkasten

Viele Dinge, die für die Entwicklung webbasierter Anwendungen benötigt werden, sind bereits in Play! integriert bzw. lassen sich über Module nachrüsten. Standardmäßig an Bord sind bereits Module für Volltextsuche, Security, Google Web ToolkitGoogle App Engine, Spring-Support, OpenID, E-Mail-Versand, Job-Scheduling über Quarz, Captchas und vieles andere mehr. Gerade die Volltextsuche, die auf Apache Lucene basiert, kann für alle, die eine Suchfunktion benötigen, ein großer Pluspunkt sein. Nach der Aktivierung des Moduls können ganze Model-Klassen oder einzelne Properties zur Volltextindexierung markiert werden. Sowohl die Indexierung als auch das Suchen nach Einträgen basieren auf der Hibernate Lucene-Erweiterung, allerdings durch einfache Frameworkklassen gekapselt. Zum Zeitpunkt der Artikelentstehung ist ein Modul-Repository in Vorbereitung, in dem Module von Drittentwicklern zusammengefasst werden sollen. Die Play!-Community hat hier bereits einige Dinge in Vorbereitung und man darf gespannt sein, was sich in den nächsten Monaten hier so tut.

Online

Der bereits angesprochene, in Play! enthaltene HTTP-Webserver ist für den Einsatz auf einem Entwicklungssystem absolut ausreichend, die Macher von Play! vertreten auch die Meinung, dass dieser durchaus für Seiten bzw. Anwendungen mit mittelgroßer Last ausreichend sind, als Verantwortlicher einer solchen Anwendung wird man aber bedeutend ruhiger schlafen können, wenn ein „gestandener“ und ausgereifter Server zum Einsatz kommt. Ein Kommandozeilenbefehl erzeugt das dazu notwendige WAR-File, das alle Dateien enthält, die für ein Deployment auf einem Web- oder Application-Server notwendig sind. Ein Deployment auf Tomcat, Jetty oder einem Application-Server, der auf einem von beiden basiert, ist damit kein Problem und wurde von vielen Play!-Anwendern bereits erfolgreich durchgeführt.

Wer dem integrierten Webserver den Vorzug geben möchte, hat prinzipiell zwei Möglichkeiten, diesen zu verwenden. Die erste Variante ist die Standalone-Nutzung von Play!, in diesem Fall werden Sie wahrscheinlich den Port von 9000 auf 80 umstellen wollen. Dies kann glücklicherweise mit wenigen Handgriffen in der application.conf geändert werden. Dort lassen sich auch andere für ein Produktivsystem wichtige Einstellungen vornehmen, die beispielsweise das Logging betreffen. Wer mehr als eine Anwendung auf einem Server betreiben möchte, der kommt nicht um einen Proxy-Webserver herum, der virtuelles Hosting unterstützt. Lighttpd oder Apache mit mod_proxy bieten sich hierfür an. Die notwendige Konfiguration wird ausführlich in der Play!-Dokumentation beschrieben.

Fazit

Das Play!-Framework ist auf einem guten Weg hin zu einer stabilen Umgebung für größere Projekte. Altgedienten Java-Webentwicklern werden sich wahrscheinlich daran stören, dass Play! nicht auf Servlets basiert. Dies ist, wie bereits erwähnt, Vor- und Nachteil zugleich. Die beiden größten Knackpunkte sind das junge Alter des Frameworks und die Dokumentation. Letztere ist nicht wirklich schlecht, so richtig ausführlich ist sie aber auch nicht. Das junge Alter spiegelt sich hauptsächlich in der geringen Verbreitung wieder. Support findet im Moment nur in der Mailing-Liste statt. Wer sich daran nicht stört, der bekommt ein Werkzeug an die Hand, mit dem Rapid Application Development nicht nur eine leere Worthülse ist, sondern Alltag werden kann.

Timo Haberkern ist Leiter Softwareentwicklung bei der Firma ROTEX Heating Systems GmbH und dort unter anderem verantwortlich für die Entwicklung von webbasierter Enterprise-Software. Zudem schreibt er regelmäßig in wichtigen deutschen Fachmagazinen, ist Autor des ersten deutschen Symfony-Buches und arbeitet als freiberuflicher Trainer für PHP, Zend Framework, Flex und Symfony (www.shift-up.de).
Geschrieben von
Timo Haberkern
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.