2014-10-09 11 views
7

Sto cercando di capire come creare e modificare i collegamenti in Spring HATEOAS.Come inserire e pubblicare collegamenti con Spring HATEOAS

Ad esempio, supponiamo di avere due raccolte, una per API/utenti e un'altra per API/evento. Vorrei associare un utente api/user/56 con un evento api/evento/21. Per ragioni di argomenti questo è un numero molti-a-molti: un utente può partecipare a molti eventi, un evento può avere molti utenti.

Da quello che ho capito, il modo per farlo è usare gli URI come chiavi primarie, quindi potrei postare quanto segue su api/user/56/events;

{ 
    attends: "http://localhost:9090/api/event/21" 
} 

L'endpoint quindi ha bisogno di essere in grado di analizzare l'URL ed estrarre l'ID (in questo caso 21) e il controller (EventController.class) in modo che io possa persistere questa.

Domanda 1: È questo il modo corretto di trattare le relazioni in Spring Hateoas in termini di API REST?

Domanda 2: Come posso risolvere questo URL in un controller per una maniglia utilizzabile sui dati (ad esempio, un riferimento al controllore/metodo appropriato, una chiave primaria, ecc)

Research

RestTemplate può essere utilizzato per richiedere i dati dal controller all'interno del metodo mappato a richiesta, in questo modo;

RestTemplate restTemplate = new RestTemplate(); 
ResponseEntity<EventResource> response = restTemplate.getForEntity(attendsUrl, EventResource.class); 
EventResource eventResource = response.getBody(); 

Comunque non credo che eventResource deve restituire un campo ID come parte dei dati - non è molto riposante e questo sarebbero esposti sulle API. Un approccio è quello di avere un parametro "includePK = true", ma ancora una volta non sembra giusto - sta solo nascondendo il problema. Inoltre l'idea del server che fa richieste alla propria API in questo modo sembra tortuosa.

Aggiornamento

C'è una questione aperta per questo qui https://github.com/spring-projects/spring-hateoas/issues/292. Basato su alcuni commenti (da parte dell'utente kevinconaway) da questo problema, ho creato una classe di utilità rapida che offre una soluzione semplice qui: SpringHateoasUtils. La soluzione si riduce a;

String mapping = DISCOVERER.getMapping(targetClass, targetMethod); 
UriTemplate template = new UriTemplate(mapping); 
//values is key/value map of parameters that the referenced method accepts 
Map<String, String> values = uriTemplate.match(uri); 

SpringHateoasUtils rende questo un po 'più bello, ma si sente ancora come dovrebbe essere una caratteristica. Cercherò di ottenere qualcosa nel codice sorgente per questo - quando è chiaro cosa sta succedendo con questo, risponderò a questa domanda.

+0

Si potrebbe inviare 'http: // localhost: 9090/api/evento/21' solo. Spring HATEOAS non ti aiuta a dereferenziare un URL.È pensato solo per le risposte, non per le richieste. Potresti dare un'occhiata a [Spring Data REST] (http://projects.spring.io/spring-data-rest/) – zeroflagL

+0

Dopo aver lavorato con Spring HATEOAS per diversi mesi, sicuramente non sembra supportare REST correttamente, quindi hanno dovuto attuare soluzioni alternative simili a ciò che state descrivendo. –

risposta

1

Guardate la risposta qui:

POSTing a @OneToMany sub-resource association in Spring Data REST

Domanda 1) Sì, questo è il modo di postare link/Relazioni. Con URI.

Domanda 2) L'URI della risorsa in realtà IS è il suo ID dal punto di vista del cliente. Il server interno risolve automaticamente questo URI nell'istanza modello reale con

org.springframework.data.rest.core.UriToEntityConverter.convert(...)

+0

Questa è una domanda su Spring Hateoas - sebbene Spring Data Rest consenta un uso limitato di link, Spring Data Rest non è in grado di fornire un modo per implementare la propria funzionalità di gestione dei collegamenti. –

+0

Ciao Andrew! Hai visto il link che ho postato? Mi ci è voluto un po 'per capire le sottili differenze. Ma intanto ho scoperto come archiviare ciò che stai cercando di fare: Spring Data HATEOAS permette di "creare" collegamenti tra entità inserendo un testo/uri-list, ad es. così: 'curl -X PUT -H" ContentType: text/uri-list "http: // localhost: 8080/api/myEntitty/1' con il link uri come payload' http: // localhost: 8080/api/myLinkedChildEntity/4711' Se hai bisogno di più accessi a basso livello puoi sempre implementare il tuo @RestController nel riposo primaverile – Robert