Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does RestTemplate not bind response representation to PagedResources?

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 no content 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?!

like image 959
user3563584 Avatar asked Apr 23 '14 08:04

user3563584


People also ask

Is RestTemplate deprecated?

RestTemplate provides a synchronous way of consuming Rest services, which means it will block the thread until it receives a response. RestTemplate is deprecated since Spring 5 which means it's not really that future proof.

How Rest Template works?

Rest Template is used to create applications that consume RESTful Web Services. You can use the exchange() method to consume the web services for all HTTP methods. The code given below shows how to create Bean for Rest Template to auto wiring the Rest Template object.

What is exchange method in RestTemplate?

The exchange method executes the request of any HTTP method and returns ResponseEntity instance. The exchange method can be used for HTTP DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT, TRACE methods. Using exchange method we can perform CRUD operation i.e. create, read, update and delete data.

What are the advantages of the RestTemplate?

RestTemplate class is an implementation of the Template method pattern in the Spring framework. It simplifies the interaction of RESTful Web Services on the client-side. It's right time to invest in Cryptocurrencies Dogecoin !


1 Answers

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:

  1. 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.

  2. Set up a custom MappingJackson2HttpMessageConverter and customize the ObjectMapperto get the Jackson2HalModule 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)); 
like image 134
Oliver Drotbohm Avatar answered Sep 17 '22 19:09

Oliver Drotbohm