2016-07-19 23 views
4

Ich verwende Spring Data REST 2.5.1, Jackson 2.8.0, Spring Boot 1.3.6.Spring Data REST - Liste der Entitäten konsumieren, Java HATEOAS-Client

Ich versuche, eine einfache Liste von Entitäten aus meinem Repository über RestTemplate zu erhalten. Ich kann den Endpunkt in einem Browser treffen und die erwarteten HAL-Daten erhalten. Das Abrufen einer einzelnen Entität funktioniert wie folgt. Diese verwenden alle die Standard-SDR-Endpunkte (z. B. localhost: {port}/myEntity).

ResponseEntity<Resource<MyEntity>> responseEntity = 
    new RestTemplate() 
     .exchange(
     uri + "/1", 
      HttpMethod.GET, 
      HttpEntity.EMPTY, 
     new ParameterizedTypeReference<Resource<MyEntity>>() {}, port 
     ) 

Oder neue RestTemplate(). GetForEntity (uri + "/ 1", MyEntity.class, port)

Wie viel SO scheinen Fragen, um anzuzeigen, Beispiele für das Abrufen einer Liste zu finden ist ein Problem. Ich habe versucht, die ParameterizedTypeReference mit Resources, Resource, MyEntity, ein Array, Liste. Alles ohne Glück.

 ResponseEntity<Resources<Resource<MyEntity>>> responseEntity = 
      new RestTemplate() 
        .exchange(
        uri, 
        HttpMethod.GET, 
        HttpEntity.EMPTY, 
        new ParameterizedTypeReference<Resources<Resource<MyEntity>>>() {} 
      , port 
      ) 

Wenn wie oben mit so ziemlich jeder Sorte namens von Resources, Resource, List<MyEntity>, MyEntity usw., die ResponseEntity leer. Wie:

<200 OK,Resources { content: [], links: [] },{Server=[Apache-Coyote/1.1], Content-Type=[application/json;charset=UTF-8], Transfer-Encoding=[chunked], Date=[...]}> 

Die Zeichenfolge JSON sieht wie unten im Browser aus.

{ 
"_embedded" : { 
"myEntities" : [ ... ] 
}, 
"_links" : { 
"self" : { 
    "href" : "http://localhost:8080/myEntity" 
}, 
"profile" : { 
    "href" : "http://localhost:8080/profile/myEntity" 
}, 
"search" : { 
    "href" : "http://localhost:8080/myEntity/search" 
} 
}, 
"page" : { 
    "size" : 20, 
    "totalElements" : 10, 
    "totalPages" : 1, 
    "number" : 1 
} 
} 

Repository Definition:

@RepositoryRestResource(collectionResourceRel = "myEntities", path = "myEntity") 
public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, Long> 
, QueryDslPredicateExecutor<MyEntity> 
, QuerydslBinderCustomizer<QMyEntity> { } 

Irgendwelche Gedanken auf, was mir fehlt?

+0

Wenn Sie sich die Struktur von 'Resources' ansehen, werden Sie feststellen, dass sie sich von der Struktur des JSON-Dokuments unterscheidet. Es ist, als ob du mit deinem Autoschlüssel dein Haus öffnen möchtest. – zeroflagL

+0

Ja, ich verstehe, dass die Art, wie ich versuche, nicht funktioniert. Ich versuche herauszufinden, was funktioniert, nicht was nicht. Wenn SDR dieses Format erstellt, muss eine Spring-Klasse vorhanden sein, die es zu konsumieren erwartet. Ich sollte nicht für das Standardformat selbst rollen müssen. – JudgingNotJudging

+1

Die Basis für das Dokument in Ihrem Beispiel ist 'PagedResources'. '_embedded' beruht auf 'EmbeddedWrapper'. Aber es gibt keine Klasse, die das Dokument direkt darstellt. Das Dokument wird dynamisch erstellt, da die _embedded-Eigenschaft dynamisch ist. – zeroflagL

Antwort

5

Ich löste das, indem ich ein paar Dinge tat.

  1. Ich musste auf Spring-hateoas aktualisieren: 0.20.0.RELEASE von 0.19.0. spring-hateas: 0.19.0 unterstützte Jacksons 2.7+ nicht wie angegeben here.

  2. Ich habe meinen Client für den Anruf wie folgt aktualisiert.

    ObjectMapper mapper = builder.build() 
    MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); 
    
    messageConverter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")) 
    messageConverter.setObjectMapper(mapper) 
    
    ResponseEntity<PagedResources<MyEntity>> responseEntity = 
         new RestTemplate(Arrays.asList(messageConverter)) 
           .exchange(
           uri, 
           HttpMethod.GET, 
           HttpEntity.EMPTY, 
           new ParameterizedTypeReference<PagedResources<MyEntity>>() {}, port 
         ) 
    

PagedResources sieht nun wie folgt aus:

<200 OK,PagedResource { content: [{<List of MyEntities>}], metadata: Metadata { number: 0, total pages: 1, total elements: 10, size: 20 }, links: [<List of hateoas links for MyEntities>] },{Server=[Apache-Coyote/1.1], Content-Type=[application/hal+json;charset=UTF-8], Transfer-Encoding=[chunked], Date=[Thu, 21 Jul 2016 14:57:18 GMT]}> 

@ zeroflagL Kommentar hat mich näher an der PagedResources Implementierung suchen, die schließlich zur führte 'Aha!' Moment mit diesem blog.

Das relevante Bit ist, dass der Standardwert RestTemplate den Accept-Header nicht auf application/hal+json setzt. Stattdessen ist der Standardwert application/x-spring-data-compact+json;charset=UTF-8, der keine Inhalte und nur Links enthält. Aus diesem Grund erhielt ich leere Inhalte für meine Resources Typen. Durch explizites Festlegen des MediaType wie oben wurde das Problem behoben.