1

I have a service with pagination index starting from 1.I get the list of entity after some logic I return the same(responses) as below

totalCount = responses.size();
return new PageImpl<>(responses, pageable, totalCount);

and when I have requested the 1st page as

new PageRequest(1, 100)

I get back the response as

{"content": [
       {
            "id": "e1",
        }{
            "id": "2",
        }
     ],
    "last": false,
    "totalElements": 102,
    "totalPages": 2,
    "size": 100,
    "number": 1,
    "sort": null,
    "first": true,
    "numberOfElements": 2
}

Here even though I have "numberOfElements": 2 I get back "totalElements": 102

The issue which I found is because of pageable.getOffset() calculation in PageImpl

this.total = !content.isEmpty() && pageable != null && pageable.getOffset() 
+ pageable.getPageSize() > total
                ? pageable.getOffset() + content.size() : total;

In my scenario for the 1st Page I'am getting offset as 100 (1*100). How do I resolve this.

Note : I use a third party service to get the responses which is indexed 1 . So I am trying to align my service to that so that the entire logic follow the same indexing.

Raj gopal
  • 114
  • 3
  • 12
  • If it is of any use, you can configure Spring Data to use 1 rather than 0 for the first page as outlined here: https://stackoverflow.com/questions/27032433/set-default-page-size-for-jpa-pageable-object/27034846#27034846 – Alan Hay Oct 19 '17 at 14:55

2 Answers2

2

The result you get is correct, since PageRequest used zero-based pages as stated in the API docs:

Parameters:

page - zero-based page index.

size - the size of the page to be returned.

So that means you're retrieving the second page (not the first one), and since you have a limit of 100 records and a total of 102 records, you'll only retrieve the last two of them.

You can still expose a 1-based number though:

new PageRequest(page-1, 100);

Alternatively, you can customize this by implementing Pageable. This allows you to override the actual offset being used by Spring data.

Nonetheless, this doesn't change the fact that Spring data expects getPageNumber() to be a zero based number. You cannot change that, you can only add an abstraction layer on top of it to make it meet your requirements.

Community
  • 1
  • 1
g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • You can (or at least could in the past) configure 0/1 for the first page https://stackoverflow.com/a/27034846/1356423. The default was actually 1 in early versions of the Spring Data library. – Alan Hay Oct 19 '17 at 14:51
1

And what's wrong with that? totalElements tells you how many elements are stored within the data source. numberOfElements tells you how many elements the current page contains. When have 102 elements in total and you requesting page 2 with size 100, you should get exactly the response you received.

What probably confuses you:

With new PageRequest(1, 100) you are requesting the 2nd page as the index starts at 0.

Herr Derb
  • 4,977
  • 5
  • 34
  • 62
  • Yes.So I want PageRequest to be aligned with the service as when I give Page request new PageRequest(1, 100) It should treat it as 1st page.Is there any way for the same other than implementing a Custom PageImpl and overriding the offset logic. – Raj gopal Oct 19 '17 at 12:28
  • No. That is something you do not change! If you want to get page one you have to do `new PageRequest(0, 100)`. What would be the benefit of it anyway? In Java (actually in most every language) indexes are 0-based. – Herr Derb Oct 19 '17 at 12:29
  • If I do that the total elements would be correct but the Page number would be 0 and user have requested for Page number 1. I have this scenario because for getting the responses I use a third party service which is indexed 1. – Raj gopal Oct 19 '17 at 12:31
  • This is an index. The first index always starts at 0. Starting an index at 1 will generally end in problems. Read this article for a scientific reasoning: http://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/EWD831.html – Herr Derb Oct 19 '17 at 12:33
  • Look at it this way: in `new PageRequest(0, 100)` the `0` means the offset from the possible page list. Means you will skip 0 pages, leading to the first page. Having `new PageRequest(1, 100)` means you want to skip 1 page and therefor get page 2. – Herr Derb Oct 19 '17 at 12:35
  • @Rajgopal what do you mean with "the user requested"? This number is a technical detail, if you don't want to expose it, you just do minus one in your service and pass that value to the `Page`. – g00glen00b Oct 19 '17 at 13:11
  • @g00glen00b I have this scenario because for getting the responses I use a third party service which is indexed 1 . So I am trying to align my service to that so that the entire logic follow the same indexing. – Raj gopal Oct 19 '17 at 13:36
  • @Rajgopal Your service can perfectly use a 1-based index, you'll just have to subtract 1 from it when you use Spring data. – g00glen00b Oct 19 '17 at 14:26