Höchster Reifegrad für REST mit HATEOAS

Seite 3: Kommunikation mit HAL

Inhaltsverzeichnis

Das HAL-Format (Hypertext Application Language) liegt zurzeit bei der IETF als Internet Draft vor. Es wird von Spring HATEOAS verwendet und setzt voraus, dass eigene Relationen einen geeigneten Weg zum Client finden. Das lässt sich beispielsweise durch die Verwendung von Spring REST Docs erreichen. Der Medientyp für eine Response wäre hal+json beziehungsweise hal+xml. Das folgende Listing zeigt eine Beispiel-Response in hal+json:

{
"_links": {
"self": {
"href": "/station/1" },
"delete": {
"href": "/station/1" }
},
"id":"1"
}

Zusätzlich existiert die Möglichkeit, Ressourcen einzubetten, um beispielsweise jedem Member weitere Links hinzuzufügen. Allerdings kann der Client nicht auf Änderungen an den Payloads reagieren. Er geht immer davon aus, dass sein Verständnis davon das gleiche wie am Server ist. Auch verzichtet der Ansatz auf das Übertragen von HTTP-Verben, obwohl sie am Server bekannt sein müssen. Das führt wie im vorherigen Listing dazu, dass mehrere Relationen zur gleichen URL führen können, obwohl sie semantisch etwas vollkommen anderes bedeuten. Das provoziert am Client Zugriffe, die recht umständlich sind, wie folgendes Listing in Pseudocode zeigt:

// for delete
response.followRel("delete").withDelete();
//for getting self
resonse.followRel("self").withGet();

In Spring HATEOAS (Client) gilt die implizite Voraussetzung, dass alle Links GET-Anfragen sind (Stand Version 0.20.0).

Fieldings zweiter Vorschlag ist, auf neue Medientypen zu verzichten und stattdessen bestehende durch neue Links zu erweitern:

Link: </stations/1>; 
rel="delete self";
type = "application/custom.v1"

Entwickler können das erreichen, indem sie, wie in RFC5988 beschrieben, die Links in den Response-Header schreiben. Das Jersey-FrameworkJersey-Framework verwendet diesen Ansatz.

Der Medientyp bleibt von der Verlinkung unbeeinflusst. Dabei entstehen ähnliche Probleme wie beim HAL-Format, da keine HTTP-Methoden mitgeliefert werden. Durch das im Link vorhandene type-Attribut kann der Client Informationen über den Medientyp der Ressource erhalten und bei entsprechender Versionierung der Typen im Vorfeld mitbekommen, ob seine Vorstellung noch mit der des Servers übereinstimmt. Dieses Vorgehen birgt aber die oben beschriebenen Gefahren. Erschwerend kommt hinzu, dass sich Header-Links nicht im Payload einbetten lassen.

Die oben beschriebenen Nachteile werden durch JSON Hyperschema behoben. Diese Spezifikation liegt zurzeit bei der IETF als Draft Version 4 vor. Die zentrale Rolle spielt dabei das Link Description Object (LDO). Ein einfaches Beispiel sieht folgendermaßen aus:

1 {
2 "rel": "add-comment",
3 "method": "POST",
4 "href": "http://example.org/api/stations/1/",
5 "targetSchema": {},
6 "schema": {
7 "type": "object",
8 "properties": {
9 "message": {
10 "type": "string"
11 }
12 },
13 "required": [ " message " ]
14 }
15 }

Das Listing zeigt ein LDO mit einer HTTP-Methode (3), einem Schema (6) beziehungsweise Target-Schema (5). Dabei ist im Feld schema ein JSON-Schema für den Payload angegeben, den die Ressource erwartet – beziehungsweise bei einem GET-Request die möglichen Request-Parameter. Im Feld targetSchema steht ein Schema für den zu erwartenden Payload.

Wenn die Schnittstelle dem CQRS-Prinzip (Command Query Responsibility Segregation) folgt, sollte möglichst immer nur eines der beiden Schemata belegt sein. Ein GET-Request bildet wiederum eine Ausnahme, da er durchaus mit Query-Parametern versehen sein kann. Da REST-Schnittstellen in den meisten Fällen eher leseoptimiert sein sollten, ist das Aufbauen von separaten Lese- und Schreibmodellen meist eine sehr gute Idee.

Die Angabe der HTTP-Methode reduziert menschliche Fehler beim Zugriff auf die Schnittstelle, da er genau definiert ist. Außerdem kann man durch die Angabe der beiden Schemata die Vorstellung der Clients im Vorfeld mit der des Servers abgleichen und gutartige Veränderungen in den Schemata kompensieren. Dadurch lassen sich unter anderem Felder ausblenden, die nicht mehr in den Schemata auftauchen. Ein konformes JSON Hyperschema enthält auf der höchsten Ebene in der Eigenschaft "schema", ein Array, das eine beliebige Zahl von LDOs als erlaubte Links enthalten kann.