1

I want to consume a paginated API. The API is provided by an endpoint, created with SpringBoot. While looking for a solution I found this post on StackOverflow.

Almost every answer recommends to create a POJO to parse into. But since this is a standard problem, there should be a standard solution which is supported by the framework. In the mentioned post there is an answer by Vladimir Mitev. He recommands the use of ParameterizedTypeReference<PagedResources<T>>. I took his snipped and changed the Type Tfor my purpose:

restTemplate.exchange(targetUrl, HttpMethod.GET, requestEntity, new ParameterizedTypeReference<PagedResources<String>>() {});

And this worked for getting the content of the Page. But the Problem here is, that the provided metadata keeps being null. Thus I am unable to iterate over the pages since I do not get the information about totalPages. Am I defining the ResponseType correctly? Debbuging led me to clue that the default constructor of PagedResources is called, so the PageMetadata Object is never set.

In the following I describe how I approached the problem. Maybe it helps others, that face the same problem

The naive way to consume the paginated API was:

restTemplate.exchange(targetUrl, HttpMethod.GET, requestEntity, String.class);

This gives us an idea of the underlying datascructure, which looks like this.

<200,
{
   "content":[
      "Data1",
      "Data2",
      "Data3"
   ],
   "pageable":{
      "sort":{
         "sorted":false,
         "unsorted":true,
         "empty":true
      },
      "offset":0,
      "pageSize":20,
      "pageNumber":0,
      "paged":true,
      "unpaged":false
   },
   "number":0,
   "sort":{
      "sorted":false,
      "unsorted":true,
      "empty":true
   },
   "size":20,
   "first":true,
   "numberOfElements":20,
   "totalPages":5,
   "totalElements":90,
   "last":false,
   "empty":false
},
[
   Cache-Control:"no-cache, no-store, max-age=0, must
-revalidate",
   Content-Type:"application/json;charset=UTF-8",
   Date:"Thu, 20 Jun 2019 17:38:18 GMT",
   Expires:"0",
   Pragma:"no-cache",
   Server:"nginx/1.15.10",
   X-Content-Type-Options:"nosniff"

It looks like a standard spring pagionation response object. So there should be a way to directly transform this response into some kind of pre defined object.

Therefore I tried changing the ResponseType parameter: Page.class resulting in

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.domain.Page]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of org.springframework.data.domain.Page (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

and PageImpl.class resulting in

org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.domain.PageImpl]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of org.springframework.data.domain.PageImpl (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

So there has to be another ResponseType to parse the response into.

froehli
  • 904
  • 1
  • 11
  • 35

0 Answers0