Why does RestTemplate not bind response representation to PagedResources?
As you've discovered correctly, PagedResources
does not have an _embedded
property, that's why you don't get the content
property populated.
This dilemma can be solved in two different ways:
Providing a type that matches the representation in the first place. Thus, craft a custom class and either stick to the property names of the representation or customize it using Jackson annotations etc.
Set up a custom
MappingJackson2HttpMessageConverter
and customize theObjectMapper
to get theJackson2HalModule
configured that Spring HATEOAS ships out of the box.ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.registerModule(new Jackson2HalModule()); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); converter.setObjectMapper(mapper); RestTemplate template = new RestTemplate(Collections.<HttpMessageConverter<?>> singletonList(converter));
user3563584
Updated on June 07, 2022Comments
-
user3563584 almost 2 years
I am using spring-data-rest to expose entities as (paged) rest resources. Everything works fine, but when I request data via
RestTemplate
, I get an useless HATEOAS JSON (which I didn't ask for). The JSON seems to be a PagedResources. I could live with that, but the JSON isn't converted into an object correctly. There is nocontent
inside.Repository:
@RepositoryRestResource(collectionResourceRel = "people", path = "people") public interface PersonRepository extends PagingAndSortingRepository<Person, Long> { List<Person> findByLastName(@Param("name") String name); }
Client:
public List<Person> getPersons() { RestTemplate rt = new RestTemplate(); System.out.println(rt.getForObject(URL, PagedResources.class).getContent().size()); System.out.println(rt.getForObject(URL, PagedResources.class).getLinks().size()); System.out.println(rt.getForObject(URL, PagedResources.class).getMetadata().getTotalElements()); return new ArrayList<Person>(rt.getForObject(URL, PagedResources.class).getContent()); // <-- empty }
System.out:
0 // getContent().size() 4 // getLinks().size() 2 // getTotalElements()
curl:
C:\...>curl http://localhost:8080/spring-jsf-rest/rest/people { "_links" : { "self" : { "href" : "http://localhost:8080/spring-jsf-rest/rest/people{?page,size,sort}", "templated" : true }, "search" : { "href" : "http://localhost:8080/spring-jsf-rest/rest/people/search" } }, "_embedded" : { "people" : [ { "firstName" : "John", "lastName" : "Rambo", "_links" : { "self" : { "href" : "http://localhost:8080/spring-jsf-rest/rest/people/1" } } }, { "firstName" : "Chuck", "lastName" : "Norris", "_links" : { "self" : { "href" : "http://localhost:8080/spring-jsf-rest/rest/people/2" } } } ] }, "page" : { "size" : 20, "totalElements" : 2, "totalPages" : 1, "number" : 0 } }
It seems like
_embedded
is not mapped correctly to content?! -
user3563584 about 10 yearsbig thanks for your help. option 2 looks nice. but i get "Unrecognized field "templated" (class org.springframework.hateoas.Link), not marked as ignorable (one known property: "href"])". i guess i have to dig deeper. if i cant get it to work, i guess ill stick to option 1.
-
norgence about 10 yearsI think you can simply get rid off this by setting
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
. Jackson is quite strict by default. Updated the answer accordingly. -
Stefan Falk about 6 yearsHm, if I do that things break for me - any idea?
-
Soumitri Pattnaik over 5 years@OliverDrotbohm I am having the same issue, the difference is I am not using RestTemplate instead I am using FeignClient. What can I do?