Search code examples
springrestresttemplate

Spring RestTemplate with paginated API


Our REST APIs are returning results in Pages. Here is an example of one Controller

@RequestMapping(value = "/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
@ResponseStatus(HttpStatus.OK)
public Page<MyObject> findAll(Pageable pageable) {
  ...
}

Is there an easy way to consume that API with RestTemplate?

if we do

ParameterizedTypeReference<Page<MyObject>> responseType = new ParameterizedTypeReference<Page<MyObject>>() { };

ResponseEntity<Page<MyObject>> result = restTemplate.exchange(url, HttpMethod.GET, null/*httpEntity*/, responseType);

List<MyObject> searchResult = result.getBody().getContent();

it throws an exception

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not construct instance of org.springframework.data.domain.Page, 
problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information at [Source: java.io.PushbackInputStream@3be1e1f2; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.data.domain.Page, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information

Thank you in advance


Solution

  • Changed the code reading the Rest API response as;

    ParameterizedTypeReference<RestResponsePage<MyObject>> responseType = new ParameterizedTypeReference<RestResponsePage<MyObject>>() { };
    
    ResponseEntity<RestResponsePage<MyObject>> result = restTemplate.exchange(url, HttpMethod.GET, null/*httpEntity*/, responseType);
    
    List<MyObject> searchResult = result.getBody().getContent();
    

    And here is the class I created for RestResponsePage

    package com.basf.gb.cube.seq.vaadinui.util;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.Pageable;
    
    public class RestResponsePage<T> extends PageImpl<T>{
    
      private static final long serialVersionUID = 3248189030448292002L;
    
      public RestResponsePage(List<T> content, Pageable pageable, long total) {
        super(content, pageable, total);
        // TODO Auto-generated constructor stub
      }
    
      public RestResponsePage(List<T> content) {
        super(content);
        // TODO Auto-generated constructor stub
      }
    
      /* PageImpl does not have an empty constructor and this was causing an issue for RestTemplate to cast the Rest API response
       * back to Page.
       */
      public RestResponsePage() {
        super(new ArrayList<T>());
      }
    
    }