2015-01-02 37 views
6

Ich habe zwei Anwendungen, eine heißt bar, was mir Ressourcen im HAL-Format zur Verfügung stellt. Das andere ist bcm, um diesen Dienst zu verbrauchen.Consuming Spring Hateoas Restservice mit RestTemplate

Beispiel für die Antwort bar sieht wie folgt aus:

[ 
    { 
     "name":"Brenner/in", 
     "_links":{ 
      "self":{ 
       "href":"..host/bbsng-app-rest/betrieb/15" 
      } 
     } 
    }, 
    { 
     "name":"Dienstleistungshelfer/in HW", 
     "_links":{ 
      "self":{ 
       "href":"..host/bbsng-app-rest/betrieb/4" 
      } 
     } 
    }, 
    { 
     ... 

Jetzt versuche ich, das zu konsumieren von bcm mit Spring RestTemplate. Meine Lösung funktioniert, aber ich bin mit dieser Lösung nicht zufrieden und denke, dass es einen saubereren Weg gibt.

Kundencenter-Kodex RestService raubend wie folgt aussieht:

@Autowired private RestTemplate template; 

@Override 
@SuppressWarnings("unchecked") 
public BerufListe findeAlleBerufe() { 
    final BerufListe berufListe = new BerufListe(); 

    final ResponseEntity<List> entity = template.getForEntity(LinkUtils.findBeruf(), List.class); 

    if (OK.equals(entity.getStatusCode())) { 
     final List<LinkedHashMap> body = entity.getBody(); 
     for (final LinkedHashMap map : body) { 
      final LinkedHashMap idMap = (LinkedHashMap) map.get("_links"); 
      String id = remove(String.valueOf(idMap.get("self")), "href="); 
      id = remove(id, "{"); 
      id = remove(id, "}"); 
      final String name = String.valueOf(map.get("name")); 
      final Beruf beruf = new Beruf(id, name); 
      berufListe.add(beruf); 
     } 
    } 

    return berufListe; 
} 

Es gibt nur wenige hässlichen Code ist wie Sie sehen. Eine davon ist, dass ich keine Generika für meine Sammlungen habe. Der andere Punkt, ich bekomme die Resource_ID sehr kompliziert, und ich benutze StringUtils.remove viele Male, um die selbe URL zu extrahieren.

Ich bin sicher, es muss eine bequemere Möglichkeit geben, HAL-Response bis zum Frühjahr zu konsumieren.

Vielen Dank.

Antwort

3

Werfen Sie einen Blick auf die Resource Klasse von Spring-Hate.

Es bietet Methoden zum Extrahieren der Links aus der Antwort. Da RestTemplate jedoch erfordert, dass Sie die Klasse als Variable angeben, habe ich keinen anderen Weg gefunden, als eine Unterklasse der gewünschten Entität zu erstellen und sie für RestTemplate zu verwenden.

Sie Code könnte dann wie folgt aussehen:

public class BerufResource extends Resource<Beruf> { } 

BerufResource resource = template.getForEntity("http://example.at/berufe/1", BerufResource.class); 
Beruf beruf = resource.getContent(); 
// do something with the entity 

Wenn Sie eine vollständige Liste anfordern möchten, müssten Sie die Array-Version Ihrer Einheit RestTemplate weitergeben müssen:

BerufResource[] resources = template.getForEntity("http://example.at/berufe", BerufResource[].class); 

List<BerufResource> berufResources = Arrays.asList(resources); 
for(BerufResource resource : berufResources) { 
    Beruf beruf = resource.getContent(); 
} 

Leider Wir können Resource<Beruf>.class nicht schreiben, was den gesamten Zweck der generischen Klasse zunichtemacht, da wir für jede Entität erneut eine Unterklasse erstellen müssen. Der Grund dafür ist Typ Löschung. Ich habe irgendwo gelesen, dass sie planen, generische Unterstützung für RestTemplate einzuführen, aber mir sind keine Details bekannt.

die Extraktion der ID aus der URL Adressierung:

ich ein anderes Modell auf der Clientseite zu verwenden, würde empfehlen, und die Art des ID-Feldes mit String ersetzen und speichern Sie die gesamte URL in ihr. Auf diese Weise können Sie jederzeit die gesamte Entität erneut abrufen und müssen die URL nicht selbst erstellen. Sie werden die URL später trotzdem benötigen, wenn Sie POST-Anfragen an Ihre API senden möchten, da Sie von Spring-hateaos den Link anstelle der ID senden müssen. Eine typische POST-Anfrage könnte wie folgt aussehen:

{ 
    "firstname": "Thomas", 
    "nachname": "Maier", 
    "profession": "http://example.at/professions/1" 
} 
+0

Jedes Update mit dem letzten Versionen für diese Antwort? – Snekse

+0

Leider nicht. Aber ich habe seitdem auch nicht viel geforscht. –

+2

Sie können 'new ParameterizedTypeReference >() {}' verwenden, um Unterklassen zu vermeiden. – afaulconbridge