Enterprise Java Web Services

2 RESTful Web Services mit JAX-RS

2  RESTful Web Services mit JAX-RS

Enterprise Java Web Services

2 RESTful Web Services mit JAX-RS


Seit einiger Zeit steht mit RESTful Web Services eine zweite Technologie zur Realisierung von Webdiensten zur Verfügung. Genauso wie ihre SOAP-Pendants lassen sich diese Java-Komponenten auf Basis annotierter POJOs implementieren. Wie das konkret funktioniert, zeigt dieser Teil.

Im ersten Teil dieser Serie ging es um die Entwicklung von SOAP Web Services mit JAX-WS (Java API for XML-based Web Services). Dieses Mal beschäftigen wir uns mit den speziell in der Web-2.0-Gemeinde sehr beliebten RESTful Web Services. Nach einer theoretischen Einführung in die Materie werden wir uns anhand eines Beispiels ansehen, wie der Entwickler mit JAX-RS (Java API for RESTful Web Services) solche Services erstellen kann.

RESTful Web Services

Der große Overhead bei der Abwicklung eines Methodenaufrufs führte dazu, dass neben den SOAP Web Services eine zweite, leichtgewichtigere Variante von Web Services aufkam: RESTful Web Services. Bei diesen stehen nun nicht mehr Dienste, sondern Ressourcen im Mittelpunkt des Geschehens. Jeder Service kapselt eine bestimmte Ressourcenklasse und bietet dem Nutzer über seine HTTP-Schnittstelle die Möglichkeit, den Zustand einzelner oder mehrerer Ressourcen abzufragen oder zu manipulieren. RESTful Web Services basieren auf dem von Roy Fielding geprägten Architekturstil REST (Representational State Transfer) [1], als dessen bedeutendster Vertreter sich das WWW nennen lässt. Das Web wird als eine Sammlung von Ressourcen angesehen, die untereinander verknüpft sein können. Über einen URI lässt sich jede Ressource eindeutig adressieren. Zum Transfer der Daten wird das zustandslose HTTP(S) verwendet. Die Operation, die serverseitig auf der adressierten Ressource ausgeführt wird, ist mitunter von der gewählten HTTP-Methode abhängig. Über den zurückgelieferten HTTP-Statuscode informiert der Web Service seinen Aufrufer über den Erfolg der Aktion. Gemäß Konvention kommt den HTTP-Methoden folgende Bedeutung zu:

  • GET liefert eine oder mehrere Ressourcen in einer bestimmten Repräsentation zurück
  • POST erzeugt eine Ressource
  • PUT aktualisiert eine bereits vorhandene Ressource
  • DELETE löscht eine Ressource

Jede Ressource kann verschiedene Repräsentationen aufweisen. In Verbindung mit RESTful Web Services trifft man die Formate JSON (JavaScript Object Notation) und XML häufig an. Der Nutzer kann über die Attribute Content-Type und Accept im HTTP-Header Angaben bezüglich des für die Anfrage gewählten bzw. für die Antwort akzeptierten Datenformats machen. Die Beschreibung der Web-Service-Schnittstelle erfolgt in Form der WADL (Web Application Description Language).

JAX-RS

JAX-RS [2] ermöglicht dem Java-Entwickler die Realisierung von RESTful Web Services mittels annotierter POJOs. Sie ist Teil der Java-Plattform EE 6, kann jedoch auch problemlos mit der Standardedition genutzt werden. Lediglich die fehlenden Bibliotheken müssen dann dem Klassenpfad hinzugefügt werden. Für die aktuell in der Version 1.1 vorliegende Spezifikation ist der JSR 311 verantwortlich. Jersey [3] setzt diese als Referenzimplementierung um. Die wichtigsten API-Klassen findet der Programmierer im Package javax.ws.rs.* vor.

Begleitendes Beispiel: Distributed Books

Den meisten Lesern ist wahrscheinlich das Problem bekannt, dass sich der Bücherbestand einer Softwarefirma schon recht bald auf unzählige Büros verteilt. Zur Erfassung aller Bücher und ihrer Aufbewahrungsorte wollen wir deshalb einen RESTful Web Service entwickeln. Auf das Frontend werden wir nur am Rande eingehen. Der nächste Ferienpraktikant soll schließlich auch noch etwas zu tun haben. Der Bücherdienst soll die typischen CRUD-Operationen [4] bereitstellen, da diese hinsichtlich des Formats mit XML verarbeitet werden können. Zusätzlich soll der Benutzer alle Bücher im JSON-Format abrufen sowie über einen Suchbegriff nach bestimmten Werken suchen können. In Verbindung mit den Suchergebnissen kann er zwischen den Formaten JSON und XML wählen.

Implementierung eines Web Service

Bei der Umsetzung eines RESTful Web Service reicht grundsätzlich eine einfache Klasse aus, trotzdem empfiehlt sich die Verwendung eines Interface, um dort alle Annotationen hineinzupacken. Der Entwickler hat jedenfalls alle Möglichkeiten: Er kann die Annotationen im Interface (sofern er eines verwendet) in der Klasse oder auf beide verteilt notieren. Die JAX-RS-Runtime ist dafür verantwortlich, zu einem eingehenden HTTP-Request die zugehörige Web-Service-Methode ausfindig zu machen, diese auszuführen und an den Aufrufer das Ergebnis im gewünschten Format zurückzuliefern. Als wesentliche Elemente eines solchen Requests lassen sich folgende ausmachen:

  • Request-URI (z. B. http://localhost:8080/resources/books)
  • HTTP-Methode (z. B. POST)
  • Medientyp der übermittelten Anfragedaten (z. B. application/xml)
  • Anfragedaten (z. B. <book title="Mule in Action" ... />)
  • akzeptierte Medientypen für die zu übermittelnden Antwortdaten (z. B. application/json)

Die Aufgabe des Programmierers besteht darin, die Methoden seines RESTful Web Service mit den von JAX-RS bereitgestellten Annotationen auszuzeichnen. Beim Eingehen eines Requests kann die Runtime durch einen Vergleich der Request-Teile mit den Annotationswerten erkennen, welche Web-Service-Methode aufgerufen werden soll.

Welche Annotationen stehen nun zur Verfügung? @Path, auf das Interface (oder die Klasse) angewendet, verwandelt das POJO in einen RESTful Web Service. Hierüber erfolgt außerdem die Angabe des URI-Pfades, wobei dieser relativ zum Kontext des Web Service Deployments interpretiert wird. Die Annotation @Path lässt sich auch direkt auf Methoden anwenden. Die Interpretation des Pfades erfolgt dabei relativ zur Pfadangabe des Interface (oder der Klasse). Zu jeder Methode wird auf diese...