Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First page number is 0 in the API response when using spring data one-indexed-parameters #2811

Closed
sundarsabapathi opened this issue Apr 4, 2023 · 8 comments
Assignees
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@sundarsabapathi
Copy link

sundarsabapathi commented Apr 4, 2023

I am using spring-boot-starter-web and spring-boot-starter-jpa to developing a REST API.
I am trying to make an API page start from 1 instead of 0.

I configured the following property spring.data.web.pageable.one-indexed-parameters=true in application.properties file.

Here is my current endpoint implementation code:

@GetMapping(value = "/alluser", produces = MediaType.APPLICATION_JSON_VALUE)
 public Page<User> getUserinfo(Pageable pageable) 
 {
      Page<User> userPage = userService.getAllUserInfo(pageable);
      List<User> userResultList = userPage.getContent();
      userResultList = userResultList.stream().map(userObj -> {
          converterService.convertToDto(userObj);
	  return userObj;
      }).collect(Collectors.toList());

      Page<User> userDtoPage = new PageImpl<>(userResultList, pageable, userPage.getTotalElements());
      return userDtoPage;
 }

When the above REST endpoint is invoked as below

http://localhost:9091/user-management/userinfo/alluser

Then I get the following response

{
  "content": [
    {
      "userId": "111",
      "userName": "First Demo"
    },
    {
      "userId": "222",
      "userName": "Second Demo"
    }
  ],
  "pageable": {
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "offset": 0,
    "pageNumber": 0,
    "pageSize": 2,
    "paged": true,
    "unpaged": false
  },
  "last": false,
  "totalElements": 8,
  "totalPages": 4,
  "size": 2,
  "number": 0,
  "sort": {
    "empty": true,
    "sorted": false,
    "unsorted": true
  },
  "first": true,
  "numberOfElements": 2,
  "empty": false
}

I am expecting the pageNumber to be 1, however it is 0.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 4, 2023
@sundarsabapathi sundarsabapathi changed the title How to make API pagination start from 1 using spring data one-indexed-parameters First page number is 0 in the API response when using spring data one-indexed-parameters Apr 5, 2023
@quaff
Copy link
Contributor

quaff commented Jun 18, 2023

@sundarsabapathi You should provide a minimal reproducer.

@sundarsabapathi
Copy link
Author

Hi @quaff, Sorry for the late reply. I reproduce the issue with minimal code and attached the zip file. Please give your feedback.

pagination-rest-api.zip

@odrotbohm
Copy link
Member

Serializing Page instances directly is not supported as it is a domain type. To render those properly considering the settings, you need to return a PagedModel available through Spring HATEOAS. You can declare a PagedResourceAssembler as handler method argument and call ….toModel(…) on that to produce a properly serialized representation.

@sundarsabapathi
Copy link
Author

Thanks @odrotbohm. I follow your suggestion to try again.

@lowcasz
Copy link

lowcasz commented Nov 2, 2023

@odrotbohm

Serializing Page instances directly is not supported as it is a domain type. To render those properly considering the settings, you need to return a PagedModel available through Spring HATEOAS. You can declare a PagedResourceAssembler as handler method argument and call ….toModel(…) on that to produce a properly serialized representation.

Regardless of it being a domain object, it looks like an error. The Page should be constructed based on Pageable and contain its parameters, similar to the PageImpl instance, even if the parameter only concerns the way Pageable is built.
Regarding HATEOAS, it would be good if there were built-in support for fixing links because it's not easy for beginners to find information on how to fix this, especially given that the same parameter could be used in spring-data-rest.

@odrotbohm
Copy link
Member

odrotbohm commented Nov 2, 2023

Regardless of it being a domain object, it looks like an error.

Page looks like an error? I cannot follow.

The Page should be constructed based on Pageable and contain its parameters, similar to the PageImpl instance, even if the parameter only concerns the way Pageable is built.

I am unable to follow here, either. The ticket is about serializing Page instances and in how far serialization to JSON is supported out of the box.

Regarding HATEOAS, it would be good if there were built-in support for fixing links because it's not easy for beginners to find information on how to fix this, especially given that the same parameter could be used in spring-data-rest.

The reference documentation contains a dedicated section on the web aspects of serializing Page/Slice. Furthermore, Spring Data REST actually uses Spring HATEOAS under the covers and does exactly what I suggested above and is laid out in the documentation.

@lowcasz
Copy link

lowcasz commented Nov 2, 2023

This seems more crazy than I thought. :/ I initially believed that the Pageable object would take the same value as in the URL, but now I see that it is modified during the binding of the address to PageRequest. This generates many problems because, from the HTTP layer, page parameter is other than page parameter in the query, but in the case of HATEOAS, the links to the beginning of the resources are incorrectly generated as they should contain page=1 instead of page=0.

This approach is very confusing, and I would consider starting a new issue to:

  • either completely remove the existence of the misleading one-indexed-parameters parameter and let users take care of customizing the binding themselves
  • or properly map both the request and response when changing the domain logic is too complicated

@odrotbohm
Copy link
Member

As a first measure, let's stop derailing the original reporter's problem with completely unrelated aspects (the way you assume query parameters to look like and work, for example).

@odrotbohm odrotbohm added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged labels Nov 2, 2023
@odrotbohm odrotbohm closed this as not planned Won't fix, can't repro, duplicate, stale Nov 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Projects
None yet
Development

No branches or pull requests

5 participants