Die FacesTales-Kolumne

RESTFul JSF: Brainstorming

Lars Röwekamp

In den letzten Jahren macht das Akronym REST (Kurzform für Represental State Transfer) in der Web- und Web-Service-Community vermehrt die Runde. Nicht wenige sehen REST als Allheilmittel in dem immer stärker wachsenden Problemdschungel. Was bedeutet dies nun aber für JSF? Sind die letzten Tage unserer Kolumne gezählt? Um es gleich vorwegzunehmen: JSF mit REST zu vergleichen, macht genau soviel Sinn wie ein Vergleich von Äpfel und Birnen. Aber es bleibt ja immer noch die Alternative „gemischter Obstsalat“.

REST aus 10 000 m

Der Begriff REST wurde bereits im Jahr 2000 von Roy Fielding im Rahmen seiner Dissertation geprägt. Fielding beschreibt hier eine Arch

itektur für Webanwendungen, die auf der Grundidee basiert, dass sich eine Anwendung vollständig durch ihre Ressourcen und den möglichen Manipulationen auf ihnen beschreiben lässt. Jede Ressource wird dabei durch ein eindeutiges URI beschrieben. Zum Zugriff auf die Ressourcen werden einfache HTTP

-Aufrufe verwendet, die sich je nach Art des Zugriffs – Anlegen, Lesen, Ändern oder Löschen der Ressource – in der verwendeten Methode unterscheiden (GET, POST, PUT oder DELETE). Mittlerweile bieten viele öffentliche Dienste ein entsprechendes REST-API an. Als Beispiel soll an dieser Stelle das Twitter-REST-API herangezogen werden, das zugegebenermaßen an der einen oder anderen Stelle nicht zu 100 % dem reinen REST-Paradigma entspricht.

Die Liste aller Status der eigenen Twitter-Freunde lässt sich via GET – http://twitter.com/statuses/friends_timeline.format erfragen. Möchte man dagegen seinen aktuellen Status committen, gelingt dies nach einer vorherigen Authentifizierung über POST – http://twitter.com/statuses/update.format. Wie nicht anders zu erwarten, kann ein einmal angelegter Status durch den Aufruf von POST oder DELETE – http://twitter.com/statuses/destroy/id.format am Ende auch wieder gelöscht werden. Spätestens an dieser Stelle fällt ein Bruch mit dem reinen REST-Paradigma auf (POST ist neben DELETE erlaubt und die gewünschte Aktion – destroy – ist im URL enthalten). Dieser Bruch trägt der Tatsache Rechnung, dass nicht alle http-Clients in der Lage sind, ein DELTE bzw. PUT abzusetzen. Das .format ist übrigens optional und steht für den gewünschten Rückgabetyp (XML, JSON, RSS, ATOM). Eine kleine Anmerkung am Rande: Auch die beiden Autoren der Kolumne twittern fleißig (@mobileLarson/Lars Röwekamp und @mwessendorf/Matthias Weßendorf).

JSF und REST?

So weit, so gut. Aber was bedeutet das in Bezug auf JSF? Zunächst einmal fällt auf, dass REST optimal für bookmarkable URLs geeignet zu sein scheint. Könnte dies also die Lösung für eines der großen JSF-Probleme – die angeblich fehlende Bookmark-Fähigkeit – sein? Die Antwort ist ein klares „Nein“. Um dies zu verstehen, muss man sich noch einmal den Hauptfokus beider Welten vor Augen halten: JSF ist ein UI-zentriertes Webframework. REST dagegen fokussiert sich auf den Service Layer einer Anwendung und stellt somit eher eine leichtgewichtige Alternative zum schwergewichtigen, SOAP-basierten Web Service dar. Das Einführen von RESTful URLs zum Aufruf eines JSF-basierten UI, nur um so ein Bookmark setzen zu können, macht also nicht wirklich Sinn. Für diesen Zweck gibt es weitaus bessere Lösungen (siehe hier oder hier) sowie ab JSF 2.0 die Möglichkeit zur direkten Generierung eines entsprechenden Links mithilfe der beiden neuen Komponenten und (siehe hier, Abschnitt 2.5.6 „Bookmarkability“).

Macht dann eine gemeinsame Verwendung von JSF und REST überhaupt einen Sinn, und wenn ja, wie könnte sie aussehen? Prinzipiell sind zwei, eigentlich sogar drei Szenarien denkbar. Zum einen kann eine JSF-Anwendung als Consumer einen RESTful Service nutzen und das Ergebnis im Anschluss visualisieren. Zum anderen kann ein Service, der innerhalb einer JSF-Anwendung genutzt wird, via REST-API auch Dritten – als Partner-API – zur Verfügung gestellt werden. In diesem Fall wäre die JSF-Anwendung der REST Service Provider. Das dritte Szenario ist eigentlich nur eine spezielle Variante des ersten, bei dem der Zugriff auf ein externes REST-API via JSF-Komponente gekapselt und so für andere JSF-Anwendungen wiederverwendbar zur Verfügung gestellt wird.

JSF REST Service Consumer

Stellen wir uns einmal folgende Aufgabenstellung vor: Ein Twitter-Client soll auf Basis von JSF implementiert werden. Der einzige Unterschied zu einer „normalen“ JSF-Anwendung besteht somit eigentlich nur darin, dass die Ressourcen – die Twitter-Status – nicht aus einer Datenbank, sondern aus einem externen Dienst via REST-API herangezogen werden müssen. Das Ganze lässt sich hervorragend in einem eigenen Service innerhalb des Service Layers der JSF-Anwendung kapseln. Der Wrapper-Service greift via HTTP (get, post, put oder delete) auf das entsprechende Twitter-API zu und parst im Anschluss den Response bzw. lässt ihn via Converter Library automatisch in die gewünschten Java-Objekte überführen. Der Zugriff auf den Twitter-REST-Service ließe sich über die HttpURLConnection realisieren. Als Converter Library könnte im Fall einer XML-Antwort JAXB und für JSON ein entsprechender JSON Marshaller verwendet werden. Noch einfacher geht der Zugriff, wenn der externe Service eine WADL (Web Application Description Language) zur Verfügung stellt. In diesem Fall kann der Client automatisch generiert werden.

JSF REST Service Provider

Soll ein interner Service einer JSF-Anwendung nicht nur zur Generierung des UI, sondern auch als REST-API nach außen zur Verfügung gestellt werden, bietet es sich an, einen zweiten Einstiegspunkt in der web.xml der Anwendung zu definieren, um so das FaceletServlet inkl. JSF LifeCycle für alle REST Calls vollständig zu umgehen. Mittlerweile existiert in der Java-Welt mit dem JSR-311 (JAX-RS API) ein Standard für die Umsetzung REST-basierter Services und mit Jersey, Apache CXF und RESTEasy finden sich bereits erste Implementierungen. Das folgende kurze Listing zeigt den Aufbau des Service-Endpoint-Interfaces eines Kundeninformationssystems gemäß JSR-311:

1.	@Path("/") 2.	@Produces("application/xml") 3.	public interface CustomerRESTEndpoint { 4.	5.	@GET 6.	@Path("/customers/") 7.	public Response getAllCustomers (); 8.	9.	@GET 10.	@Path("/customers/{customerNo}") 11.	public Response getCustomer (@PathParam("customerNo ") String customerNo); 12.	... 13.	} 

Ausblick

JSF und REST sind zwar von Haus aus nicht unbedingt optimal aufeinander eingestimmt, dies bedeutet aber nicht, dass sie nicht doch in Kombination sinnvoll genutzt werden können. Eine JSF-Anwendung kann sowohl externe REST Services konsumieren als auch selbst einen internen Service via REST-API nach außen zur Verfügung stellen. In der nächsten Ausgabe zeigen wir die bisher noch fehlende dritte Variante: Eine JSF-REST-Komponente am Beispiel von Twitter.

Geschrieben von
Lars Röwekamp
Lars Röwekamp
Lars Röwekamp ist Gründer des IT-Beratungs- und Entwicklungsunternehmens open knowledge GmbH, beschäftigt sich im Rahmen seiner Tätigkeit als „CIO New Technologies“ mit der eingehenden Analyse und Bewertung neuer Software- und Technologietrends. Ein besonderer Schwerpunkt seiner Arbeit liegt derzeit in den Bereichen Enterprise und Mobile Computing, wobei neben Design- und Architekturfragen insbesondere die Real-Life-Aspekte im Fokus seiner Betrachtung stehen. Lars Röwekamp, Autor mehrerer Fachartikel und -bücher, beschäftigt sich seit der Geburtsstunde von Java mit dieser Programmiersprache, wobei er einen Großteil seiner praktischen Erfahrungen im Rahmen großer internationaler Projekte sammeln konnte.
Kommentare

Schreibe einen Kommentar

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