Ich war schon immer ein Freund davon, nicht alles selbst zu erfinden, sondern den Austausch mit anderen zu suchen und Best Practices anzunehmen. Um so mehr war ich erfreut, in der IT-Szene München eine Vortragsankündigung der JBoss User Group München zum Thema „Java API for RestFul Web Services und RESTEasy“ zu finden. REST wurde bei uns schon länger als mögliche Schnittstelle für neue Clients diskutiert, ohne daß ich eine Ahnung gehabt hätte wie sich dieses „Protokoll“ von den bisher verwendeten WebServices unterscheidet.
Die wichtigste Erkenntnis vorneweg: REST ist kein weiteres Protokoll, um Clients anzubinden sondern ein eigener Architekturstil, der zu einem anderen Anwendungsentwurf führt. Die Referenten Stefan Tilkov und Serge Pagop präsentierten zunächst einmal die Konzepte von Rest, um dann anhand der Implementation von JBoss RESTEasy konkrete Implementierungsbeispiele zu geben. Der konzeptionelle Überblick war prägnant und unterhaltsam und hat mich überzeugt, diesen Architekturstil mindestens prototypisch einzusetzen. Die Beispielsession hätte meiner Meinung nach noch konkreter mit Edit-Compile-Run Zyklen durchgeführt werden sollen.
Bei einem WebService Modell werden die Objekte und ihre Zugriffsmethoden über WSDL/SOAP einem entfernten Klienten zur Verfügung gestellt. Es existieren Tools, um auf Basis der WSDL-Beschreibung clientseitige Stubs zu generieren und dann in der präferierten Programmiersprache auf die Ojekte im Server zuzugreifen. Es wird also das auf dem Server vorhandene Objektmodell mit den angebotenen spezifischen Operationen lokal im Client zugreifbar gemacht.
Ganz anders bei REST. REST wurde von Roy Fielding in seiner Doktorarbeit definiert. REST kann man im wesentlichen durch die folgenden 5 Merkmale beschreiben:
- Jedes „Ding“ bzw. jede Ressource hat eine ID
- Die Resourcen werden über Links verknüpft.
Der Server stellt dem Klienten die Verknüpfungen zwischen verschiedenen Ressourcen als Links zur Verfügung. Auch Statusübergänge werden als Link repräsentiert. - Es gibt standardisierte Methoden für alle Ressourcen
- Get
- Put
- Post
- Delete (und einige wenige andere)
- Jede Ressource kann verschiedene Repräsentationen haben
Es ist also möglich für verschieden Arten von Klienten unterschiedliche Repräsentationen nach außen zu geben: beispielsweise eine PDF-Repräsentation zum Drucken einer Rechnung und eine XML-Repräsentation zum Weiterleten der Teileliste an den Empfänger. Die benötigte Repräsentation wird zwischen Sender und Empfänger ausgehandelt. Selbst verschieden Versionen einer Ressource-Repräsentation können über diesen Mechanismus nach außen gegeben werden. - statuslose Kommunikation
Eine Grundannahme ist, daß der Server keine Information über den Status des Klienten hält. Der Status eines Serverobjektes kann bzw. muß jederzeit wieder abgerufen werden können. Was der Klient jedoch damit macht, ob er eine URI bereits gelesen hat, ist Sache des Klienten und nicht des Servers. Es gibt somit einen Ressourcenstatus, der im Server gespeichert wird, und einen Klientenstatus, den der Klient selbst speicher muß. Durch dieses Design kann der Server wesentlich besser skalieren.
Durch dieses einfache Modell,das in der HTTP Spezifikation festgelegt ist, können einheitliche und jedem bekannte Mechanismen für den Zugriff genutzt werden.Außerdem sind auch Fehlermeldungen mit einer festen Bedeutung vordefiniert und es ist möglich, für HTTP vorgesehene Cache- und Load-Balancing Mechanismen auch für den Zugriff auf den eigenen Backend-Server einzusetzen. Nicht zuletzt erlaubt es REST, den KLienten in jeder beliebigen Programmiersprache zu erstellen, für die eine HTTP-Client Bibliothek zur Verfügung steht.
Die REST Schnittstellen werden über Annotationen an bestehende Java Beans hinzugefügt.Die Annotationen beschreiben im wesentlichen den Pfad (die URI) einer Ressource und wie die öffentlichen Methoden mit auf Methoden der Objekte im Server und auf die Parameter dieser Methoden abbgebildet werden. Es bietet sich an, die Annotationen nicht in dem POJO selbst hinzuzufügen, sondern eine Ressourcenfassade einzuführen.
Stefan Tilkov präsentierte noch einen Ausflug zum Thema „asynchronous response handling„um aufzuzeigen, wie man in REST länger laufende Operationen oder Transaktionen modelliert. Auch hier hilft der HTTP Standard weiter: es gibt eine spezifische Antwort „202 accepted“ die in einem solchen Fall zurückgegeben werden sollte. Sie zeigt an, daß die Bearbetung nicht abgeschlossen ist.Eine vom Klienten angegebene „Return URL“ könnte vom Server aufgerufen werden, um sein Ergebnis zu posten.
Die Entscheidung für REST ändert definitiv die Architektur von Klient und Server, da nicht einfach das vorhandene Objektmodell über ein weiteres Protokoll zur Verfügung gestellt wird.Die wesentlichen Vorteile von REST sind, daß der Server einfach über einen Browser getestet werden kann und daß es einfach aus dynamischen Sprachen wie Ruby, JavaScript oder Python genutzt werden kann.
Links
- Fielding, Roy Thomas: Architectural Styles and the Design of Network-based Software Architectures. Doctoral dissertation, University of California, Irvine, 2000
- Tilkov, Stefan:A Brief Introduction to REST . Online publication, Dec 10, 2007
- RESTEasy, Online publication
- Jersey, Online publication
- Best practices for Web services versioning, Online publication
Kyle Brown, Michael Ellis, IBM January 30, 2004 - The REST Statelessness Constraint, Online Publication, Sat, 2009-Jun-13
#1 von Robert Schmelzer am 3. Juli 2009 - 14:42
Ich halte REST (neben dem prinzipellen Unterschied in der architekturellen Denkweise) schon für einen Pendelausschlag ins andere extrem ist. Den wie REST derzeit eingesetzt wird, sind es Schnittstellen ohne definierten bzw. ohne dokumentierten Format. Das heisst die Komplexität der Schnittstellenvereinbarung verlagert sich wiederum ins zwischenmenschliche bzw. erfordert es zusätzliche Dokumentation. Für einen Einsatz im B2B Beriech würde ich wenn dann auf jeden Fall strukturierte Nachrichten wie XML (mit Schema Definitionen) und Versionierung der Nachrichten einführen. Um auch die volle Eleganz mit REST auszuspielen, finde ich, dass man auch relativ lange abwärtskompatibel sowohl aus Client als auch auf Server Seite sein muss. Dann hat die etwas lockerer Handhabung der Payload auch praktische Vorteile.
Des weiteren klingt der Ansatz zwar sehr sauber, in der Praxis merkt man aber doch, dass die Welt komplexer ist.
Ein Beispiel:
1. Jedes “Ding” bzw. jede Ressource hat eine ID:
Welche ID hat eine Suchabfrage um Resourcen zu finden? Das ist dann die URL eigentlich ein Name für ein Funktion, die über Parameter konfiguriert wird. Du kannst mit der URL dann auch die klassischen Chaching verfahren nicht anwenden, da Suchfunktionen ja in Ihrer Definition jedesmal andere Ergebnisse liefern.
5. Statuslose Komunikaiton
Ist halt auch mehr Gerücht als Wahrheit. Nicht umsonst steckt man in Webanwendungen soviel Know-How in das Session Handling. Also zustandslose Kommunikaiton ist schon möglich – das ändert halt nichts an der Tatsache dass Applikationen nicht zustandslos funktionieren und man auch in einer REST Architketur Antworten dafür haben muss.
#2 von Wolfgang Strunk am 6. Juli 2009 - 10:54
Hallo Robert,herzlichen Dank für deine Kommentare. Ich möchte dir gerne zwei Antworten geben.
1. jede Resource hat eine ID
Der Ansatz jedem Ding eine ID zu geben eignet sich natürlich nicht für alles. Ich bin aber nicht bei dir, daß daß die Suchanfrage, um Ressourcen zu finden eigentlich eine Funktion referenzieren muß. Nehmen wir als Beispiel die Domäne der Unternehmenskommunikation. Ich möchte an einer Telefonkonferenz teilnehmen und muß ersteinmal die Konferenz ID finden, bevor ich der Konferenz beitreten kann. Hierbei kann die Einstiegs URI die Adresse des Konferenzservers sein, der mir als Seite alle laufenden Konferenzen, die jede wiederum eine eigene URI haben, auflistet. Caching kann ich hierfür natürlich nicht anwenden, da sich die Menge dynamisch ändert.
2. Statuslose Kommunikation
Um hier Misverständnisse zu vermeiden: ich sage nicht, daß die Applikation selbst keinen Zustand haben sollte. Wichtig ist nur, diesen Zustand nicht über Session-Data in den Klienten zu verlagern. Mir ist auch klar, daß nicht alles zustandslos abgebildet werden kann. Um aber wieder auf das Beispiel des Kommunikationsservers zurückzukommen, denke ich, daß man die wichtigsten UseCases wie „Click-To-Call“ oder „Konferenz beitreten“ durchaus statuslos realisieren kann. Die Klienten-Seite muß dann die Server Antworten entsprechend auswerten und sich einen Satus selsbt speichern oder vor jedem weiteren Call beim Server erneut abfragen.