1

If I send a request from Spring application:

public ResponseEntity<RestResponsePage<Result>> readDocs(
    Pageable pageable
) {
    HttpHeaders requestHeaders = new HttpHeaders();
    requestHeaders.add("Authorization", getToken());
    String requestUri = 
      baseAppUrl + "/api/k" + "?page={page}&pageSize={pageSize}&sort={sort}&pageable={pageable}";

    Map<String, Object> urlParameters = new HashMap<>();
    urlParameters.put("page", Integer.toString(pageable.getPageNumber()));
    urlParameters.put("pageSize", Long.toString(pageable.getPageSize()));
    urlParameters.put("sort", pageable.getSort());
    urlParameters.put("pageable", pageable);

    HttpEntity<Void> requestEntity = new HttpEntity<>(requestHeaders);

    ResponseEntity<RestResponsePage<Result>> response = restTemplate.exchange( RestResponsePage
        requestUri,
        HttpMethod.GET,
        requestEntity,
        new ParameterizedTypeReference<RestResponsePage<Result>>() {},
        urlParameters
    );
    return response;
}

to another Spring application:

@GetMapping("/")
@PageableAsQueryParam
public ResponseEntity<Page<Result>> getAll(
        @RequestHeader("Authorization") String token,
        @RequestParam("page") Integer page,
        @RequestParam("pageSize") Integer pageSize,
        @RequestParam("sort") String sort,
        @RequestParam("pageable") Pageable pageable
) {
... 
}

I have got an error saying:

Resolved [org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'org.springframework.data.domain.Pageable'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'org.springframework.data.domain.Pageable': no matching editors or conversion strategy found]

I know i can pass it seperately by fields like in example above: page, pageSize etc.

But i want also to send Sort that's is inside Pageable object - that's also not correctly deserialized as a Type Sort.

How can I make it so Pageable is correctly deserialized ?

EDIT: regarding answer, I added function like:

UriComponentsBuilder withPageable(UriComponentsBuilder builder,
                                  Pageable pageable) {
    builder.queryParam("page", pageable.getPageNumber()).queryParam("size",
        pageable.getPageSize());
    if (pageable.getSort() != null) {
        StringBuilder sb = new StringBuilder();
        pageable.getSort().forEach(order -> {
            sb.append(order.getProperty()).append(",").append(order.getDirection());
        });
        builder.queryParam("sort", sb.toString());
    }
    return builder;
}

to make sort properly deserialize.

tryingHard
  • 1,794
  • 4
  • 35
  • 74

1 Answers1

3

Do not need to use @RequestParam("pageable"). Pageable Abstract interface for pagination information. pageSize, pageNumber, sort already provided on the Pageable

Sample Controller

@Controller
public class Controller {

  @GetMapping("/...")
  public List<...> findAll(Pageable pageable) {
    log.debug("pageable: {}", pageable);
    // ...
  }

}

MockRequetBuilders

RequestBuilder request = MockMvcRequestBuilders.get("/url")
                         .param("page", "1")
                         .param("size", "5")
                         .param("sort", "name,DESC"); // column, ASC|DESC

ResultActions actions = mockMvc.perform(request);

actions.andExpect(...);

RestTemplate

URI uri = UriComponentsBuilder.fromHttpUrl("/url")
        .queryParam("page", pageable.getPageNumber())
        .queryParam("size", pageable.getPageSize())
        .queryParam("sort", pageable.getSort())
        .build()
        .toUri();

HttpHeaders headers = new HttpHeaders();
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
HttpEntity<?> entity = new HttpEntity<>(headers);

ResponseEntity<...> response = restTemplate.exchange(uri, HttpMethod.GET, entity, ...);

https://reflectoring.io/spring-boot-paging/

https://cursos.alura.com.br/forum/topico-no-primary-or-single-unique-constructor-found-for-interface-org-springframework-data-domain-pageable-195442

0gam
  • 1,343
  • 1
  • 9
  • 21
  • This does not work me, I get an error: `Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.data.domain.Pageable] with root cause java.lang.IllegalStateException: No primary or single unique constructor found for interface org.springframework.data.domain.Pageable` Check question above to see how i pass `pageable` between `backends`. I use `urlParameters.put("pageable", pageable);` – tryingHard Jun 27 '22 at 05:55
  • @tryingHard updated post and add reference link. – 0gam Jun 27 '22 at 06:50
  • you have not posted the solution in code but i found it in your links. I was missing `@Configuration @EnableSpringDataWebSupport` The second annotation makes `Pageable` deserializable. Thanks. – tryingHard Jun 27 '22 at 08:14
  • Ah, but i see some weird behaviour, that while recieved i have: `property: symbol: DESC` `direction: ASC` Added on fly `DESC` in `property` field in `pageable` I think cause of `pageable.getSort()` in your example. – tryingHard Jun 27 '22 at 08:48
  • Do you have any idea why `Spring` failes to properly `deseralize` this `sort`? Spring puts `ASC` in direction and puts correct direction next to `property` name making it invalid. So for example if property name is `symbol` the `backend` receives it as `backend DESC` and direction is set to `ASC` in `sort` part of `pageable`. – tryingHard Jun 27 '22 at 09:09
  • Ok, i found the answer, you should use function like the one I added in the question at the bottom. – tryingHard Jun 27 '22 at 09:29