Spring RestTemplate with paginated API

前端 未结 7 2061
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 17:22

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

@RequestMapping(value = \"/search\", method = RequestMethod.GET, produces          


        
相关标签:
7条回答
  • 2020-11-27 17:29

    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>());
      }
    
    } 
    
    0 讨论(0)
  • 2020-11-27 17:32

    Solution in Kotlin

    import com.fasterxml.jackson.annotation.JsonCreator
    import com.fasterxml.jackson.annotation.JsonProperty
    import com.fasterxml.jackson.databind.JsonNode
    import org.springframework.data.domain.PageImpl
    import org.springframework.data.domain.PageRequest
    import org.springframework.data.domain.Pageable
    
    import java.util.ArrayList
    
    class RestResponsePage<T> : PageImpl<T> {
        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
        constructor(@JsonProperty("content") content: List<T>,
                    @JsonProperty("number") number: Int,
                    @JsonProperty("size") size: Int,
                    @JsonProperty("totalElements") totalElements: Long?,
                    @JsonProperty("pageable") pageable: JsonNode,
                    @JsonProperty("last") last: Boolean,
                    @JsonProperty("totalPages") totalPages: Int,
                    @JsonProperty("sort") sort: JsonNode,
                    @JsonProperty("first") first: Boolean,
                    @JsonProperty("numberOfElements") numberOfElements: Int) : super(content, PageRequest.of(number, size), totalElements!!) {
        }
    
        constructor(content: List<T>, pageable: Pageable, total: Long) : super(content, pageable, total) {}
    
        constructor(content: List<T>) : super(content) {}
    
        constructor() : super(ArrayList<T>()) {}
    }
    

    and request

    var response: ResponseEntity<*> = restTemplate.getForEntity<RestResponsePage<SomeObject>>(url)
    

    Solution in Java

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.JsonNode;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class RestResponsePage<T> extends PageImpl<T> {
        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
        public RestResponsePage(@JsonProperty("content") List<T> content,
                            @JsonProperty("number") int number,
                            @JsonProperty("size") int size,
                            @JsonProperty("totalElements") Long totalElements,
                            @JsonProperty("pageable") JsonNode pageable,
                            @JsonProperty("last") boolean last,
                            @JsonProperty("totalPages") int totalPages,
                            @JsonProperty("sort") JsonNode sort,
                            @JsonProperty("first") boolean first,
                            @JsonProperty("numberOfElements") int numberOfElements) {
    
            super(content, PageRequest.of(number, size), totalElements);
        }
    
        public RestResponsePage(List<T> content, Pageable pageable, long total) {
            super(content, pageable, total);
        }
    
        public RestResponsePage(List<T> content) {
            super(content);
        }
    
        public RestResponsePage() {
            super(new ArrayList<>());
        }
    }
    
    0 讨论(0)
  • 2020-11-27 17:33

    I had to make a small change so it would ignore the unknown property of empty that seems to have been recently introduced.

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.JsonNode;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class RestResponsePage<T> extends PageImpl<T> {
        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
        public RestResponsePage(@JsonProperty("content") List<T> content,
                                @JsonProperty("number") int number,
                                @JsonProperty("size") int size,
                                @JsonProperty("totalElements") Long totalElements,
                                @JsonProperty("pageable") JsonNode pageable,
                                @JsonProperty("last") boolean last,
                                @JsonProperty("totalPages") int totalPages,
                                @JsonProperty("sort") JsonNode sort,
                                @JsonProperty("first") boolean first,
                                @JsonProperty("numberOfElements") int numberOfElements) {
    
            super(content, PageRequest.of(number, size), totalElements);
        }
    
        public RestResponsePage(List<T> content, Pageable pageable, long total) {
            super(content, pageable, total);
        }
    
        public RestResponsePage(List<T> content) {
            super(content);
        }
    
        public RestResponsePage() {
            super(new ArrayList<>());
        }
    }
    
    0 讨论(0)
  • 2020-11-27 17:35

    Expanding on above, but without the need to implement every property.

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class RestPageImpl<T> extends PageImpl<T>{
    
        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
        public RestPageImpl(@JsonProperty("content") List<T> content,
                            @JsonProperty("number") int page,
                            @JsonProperty("size") int size,
                            @JsonProperty("totalElements") long total) {
            super(content, new PageRequest(page, size), total);
        }
    
        public RestPageImpl(List<T> content, Pageable pageable, long total) {
            super(content, pageable, total);
        }
    
        public RestPageImpl(List<T> content) {
            super(content);
        }
    
        public RestPageImpl() {
            super(new ArrayList());
        }
    }
    
    0 讨论(0)
  • 2020-11-27 17:44

    The solution posted didn't work for me, because the total elements were not set correctly. I implemented the Page with a delegate pattern, which worked for me. Here's the working code:

    import org.springframework.core.convert.converter.Converter;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class RestPage<T> implements Page<T> {
        private PageImpl<T> pageDelegate = new PageImpl<>(new ArrayList<>(0));
    
        public List<T> getContent() {
            return pageDelegate.getContent();
        }
    
        public int getNumber() {
            return pageDelegate.getNumber();
        }
    
        public int getNumberOfElements() {
            return pageDelegate.getNumberOfElements();
        }
    
        public int getSize() {
            return pageDelegate.getSize();
        }
    
        public Sort getSort() {
            return pageDelegate.getSort();
        }
    
        public long getTotalElements() {
            return pageDelegate.getTotalElements();
        }
    
        public int getTotalPages() {
            return pageDelegate.getTotalPages();
        }
    
        public boolean hasContent() {
            return pageDelegate.hasContent();
        }
    
        public boolean hasNext() {
            return pageDelegate.hasNext();
        }
    
        public boolean hasPrevious() {
            return pageDelegate.hasPrevious();
        }
    
        public boolean isFirst() {
            return pageDelegate.isFirst();
        }
    
        public boolean isLast() {
            return pageDelegate.isLast();
        }
    
        public Iterator<T> iterator() {
            return pageDelegate.iterator();
        }
    
        public <S> Page<S> map(Converter<? super T, ? extends S> converter) {
            return pageDelegate.map(converter);
        }
    
        public Pageable nextPageable() {
            return pageDelegate.nextPageable();
        }
    
        public Pageable previousPageable() {
            return pageDelegate.previousPageable();
        }
    
        public void setContent(List<T> content) {
            pageDelegate = new PageImpl<>(content, null, getTotalElements());
        }
    
    
        public void setTotalElements(int totalElements) {
            pageDelegate = new PageImpl<>(getContent(), null, totalElements);
        }
    
        public String toString() {
            return pageDelegate.toString();
        }
    }
    
    0 讨论(0)
  • 2020-11-27 17:47

    When migrating from Spring Boot 1.x to 2.0, changed the code reading the Rest API response as

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.JsonNode;
    
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class RestPageImpl<T> extends PageImpl<T>{
    
        @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
        public RestPageImpl(@JsonProperty("content") List<T> content,
                            @JsonProperty("number") int number,
                            @JsonProperty("size") int size,
                            @JsonProperty("totalElements") Long totalElements,
                            @JsonProperty("pageable") JsonNode pageable,
                            @JsonProperty("last") boolean last,
                            @JsonProperty("totalPages") int totalPages,
                            @JsonProperty("sort") JsonNode sort,
                            @JsonProperty("first") boolean first,
                            @JsonProperty("numberOfElements") int numberOfElements) {
    
            super(content, PageRequest.of(number, size), totalElements);
        }
    
        public RestPageImpl(List<T> content, Pageable pageable, long total) {
            super(content, pageable, total);
        }
    
        public RestPageImpl(List<T> content) {
            super(content);
        }
    
        public RestPageImpl() {
            super(new ArrayList<>());
        }
    }
    
    0 讨论(0)
提交回复
热议问题