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?!
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.
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.
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.
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 !
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 the ObjectMapper
to 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));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With