"spring.data.web.pageable.one-indexed-parameters=true" does not work

Viewed 4590

in my Spring Boot Rest Service I want to implement a getAll method with pagination for lazy loading in frontend later.

At the moment I have to request with page 0 if I want the first set of rows. With the following config inserted in the application.properties it should work... spring.data.web.pageable.one-indexed-parameters=true ... but it doesn't.

Does anybody knows why or is this a legacy way? I'm using spring-boot-starter-web and data-jpa in version 2.0.4.RELEASE.

Thanks a lot!

edit, here is the service method, maybe PageRequest can't handle this.

public List<TransactionResponseDTO> findAll(int pageNumber, int     pageSize) {

    List<TransactionResponseDTO> transactionResponseDTOs = new ArrayList<>();

    PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);

    List<TransactionEntity> transactionEntities =
    transactionRepository.findAll(pageRequest).getContent();

    for (TransactionEntity transactionEntity : transactionEntities) {
        transactionResponseDTOs.add(convert(transactionEntity));
    }

    return transactionResponseDTOs;
}
5 Answers

The property spring.data.web.pageable.one-indexed-parameters=true only controls the behaviour of how to automatically bind pagination parameters to a web request handler method's Pageable argument.

Case 1: The default behaviour which is spring.data.web.pageable.one-indexed-parameters=false and when a request is made with http://localhost:8080/api/customers?page=5

@GetMapping("/api/customers")
public List<Customer> getCustomers(Pageable pageable) {
   //here pageable.getPageNumber() == 5
   Page<Customer> customersPage = customerRepository.findAll(pageable);
   //here customersPage.getNumber() == 5
}

Case 2: With spring.data.web.pageable.one-indexed-parameters=true and when a request is made with http://localhost:8080/api/customers?page=5

@GetMapping("/api/customers")
public List<Customer> getCustomers(Pageable pageable) {
   //here pageable.getPageNumber() == 4
   Page<Customer> customersPage = customerRepository.findAll(pageable);
   //here customersPage.getNumber() == 4
}

Note that once you get the data Page customersPage if you check customersPage.getNumber() it will simply return what is there in pageable.getPageNumber() which is 4. We might expect 5 hoping one-indexed-parameters would return 5 using 1-based indexing but that's not the case.

@Configuration
public class PageableConfig {

    @Bean
    PageableHandlerMethodArgumentResolverCustomizer pageableResolverCustomizer() {
        return pageableResolver -> pageableResolver.setOneIndexedParameters(true);
    }
}

There are lots of confustions about this on the internet. Here is the link to read more about it https://github.com/spring-projects/spring-boot/issues/14413.

Since this is not a solution to the original question but it may help dealing with this issue.

Create a utility class to create the PageRequest and then parse the paging information from the Page you get from the repository.

Explaination It just reduces the page number from the request and increases in the response. That's how the API consumer will always have one indexed page.

PagintUtils class.

public class PagingUtils {
    public static PagingInfoDto getPagingInfoFromPage(Page page){
        PagingInfoDto pagingInfoDto = new PagingInfoDto();
        int currentPage = page.getNumber() + 1;
        pagingInfoDto.setCurrentPage(currentPage);
        pagingInfoDto.setTotalPages(page.getTotalPages());
        pagingInfoDto.setTotalItems(page.getTotalElements());
        pagingInfoDto.setItemPerPage(page.getSize());
        return pagingInfoDto;
    }

    public static PageRequest getPageRequest(int pageNumber, int pageSize){
        return PageRequest.of(--pageNumber, pageSize);
    }
}

To use it for example in service layer.

Pageable pageable = PagingUtils.getPageRequest(pageNumber, pageSize);
Page<CommentEntity> page = commentsRepository.getCommentReplies(commentId, pageable);
PagingInfoDto pagingInfoDto = PagingUtils.getPagingInfoFromPage(page);

It will retrun in the json as follows.

"PagingInfo": {
        "TotalPages": 3,
        "CurrentPage": 3,
        "TotalItems": 5,
        "ItemPerPage": 2
    }

PagingInfoDto class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PagingInfoDto {
    private int totalPages;
    private int currentPage;
    private long totalItems;
    private int itemPerPage;
}
Related