In this article, I’m going to explain how to implement Spring Boot project with pagination enabled API plus sorting and filtering. Here I’m using Pageable in Spring Data Core, Spring Data JPA with MySQL based database in this practical application development and you can use the same with MongoDB or any other database you would like.

For this tutorial, I’m going to use the library REST API which I’ve developed for,

If you are really new to Spring boot and REST API development, better go through the above tutorial, or else just download the shared code from GitHub.

Technologies going to use,

  • Java 1.8
  • Spring Boot 2.3.4 RELEASE
  • JPA
  • MySQL
  • Lombok
  • Gradle
  • IntelliJ Idea for IDE

What are Pagination, Sorting, and Filtering

Let’s think we have a large set of data in our database, Eg: Book List in Amazon. So how we can show these books on a web page?

There are two ways of showing these books on a web page. 1st one is showing all books in one go in a single web page, Which could cost more memory and for a amazon like book database, That could not be done.

But the other way is divide sets from total books by given size and show selected set on a web page. Additionally here the user has an opportunity to select any set he needs to see like opening a specific page in a book. That’s simply what happens with pagination.

In Sorting we can determine how the paginated set should be sorted, Let’s assume you need to sort the whole list of books by ISBN Number (International Standard Book Numbering), There you can use sort with Spring Boot and get sorted and paginated response.

Filtering is used to filter out user selected data set from the whole dataset. Let’s say we are filtering books list by name on given name by end user. We can use filtering to do that.

How does It work With an API?

Pagination API Request

So As I explained above we can use pagination with a special request to the API, with including page number, page size and sorting. So basically you can pass those elements with your request if you don’t do that your API has the capability of setting default values for those and send a paginated response.

http://localhost:8081/api/library/book/search?page=0&size=10&sort=isbn

Here we are setting page number to the 0 which is the first page in the dataset with a size of 10 books per response and sort those books by ISBN number.

Pagination API Response

Here we can return whatever the data set which retrieve for the request by a user. But when we are using pagination we could send some more details along with the dataset coming from DB, It’s optional but good to have.

Those are the number of items in the result set and the number of total pages, These values will be usable when we consume these paginated API’s and build a frontend UI component like data tables.

{
    "bookList": [
        {
            "id": 4,
            "name": "Specification by Example",
            "isbn": "1617290084",
            "imageUrl": "https://s3.amazonaws.com/AKIAJC5RLADLUMVRPFDQ.book-thumb-images/adzic.jpg",
            "author": {
                "id": 4,
                "firstName": "Gojko",
                "lastName": "Adzic"
            }
        }
    ],
    "numberOfItems": 1,
    "numberOfPages": 1
}

Here bookList includes all the books under the given paginated request. Additionally, the response includes the total number of items and the number of total pages in separate parameters.

Developing API Endpoints

As I mentioned in the beginning, here I’m using Pageable from Spring Data core with JPA to implement this tutorial. Additionally, the mentioned library has already been added to the codebase. So you don’t need to add additional dependencies to the project.

Implementing Pagination and Sorting Enabled API Endpoint in Spring Boot

In this part, I’ll explain how we can implement pagination with sorting using pageable in the spring boot project.

So here I’ll develop separate search endpoint to search books from the database with pagination and sorting.

First, we should implement the paginated API response class to bring API response to the API consumers.

package com.javatodev.api.model.response;

import com.javatodev.api.model.Book;
import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
public class PaginatedBookResponse {
    private List<Book> bookList;
    private Long numberOfItems;
    private int numberOfPages;
}

In this example, I’m using Lombok plugin to minimize codes inside java classes. If you are not familiar with Lombok please read our article on Guide to use Lombok In Spring Boot in that article I’ve explained how we can use these new annotations like @Data and @Builder.

Then we should implement the service method to read the paginated data set from database using repository and return as PaginatedBookResponse.

To do that add following to the LibraryService.java,

public PaginatedBookResponse readBooks(Pageable pageable) {
        Page<Book> books = bookRepository.findAll(pageable);
        return PaginatedBookResponse.builder()
                .numberOfItems(books.getTotalElements()).numberOfPages(books.getTotalPages())
                .bookList(books.getContent())
                .build();
    }

Here we are getting Pageable requests from the Rest Controller level and use that to request paginated data from the Repository layer.

How to Use Pageable With JpaRepository?

Here we have developed all the Repositories using JpaRepository and It internally extends PagingAndSortingRepository, with that JpaRepository allows us to use pageable with findAll method without doing any custom implementations.

Page<T> findAll(Pageable pageable);

and It responds with Page<T> which includes all the values we need to have in our API.

So we can bind those values to the response class which we developed earlier like below.

PaginatedBookResponse.builder()            .numberOfItems(books.getTotalElements())
.numberOfPages(books.getTotalPages())
.bookList(books.getContent())
.build();

Implementing API Endpoint to Accept Paginated Request

Now we have the service implementation necessary to have in our application. Now we can set up API endpoint which accepts the paginated requests.

Just add the following API endpoint to the LibraryController.java.

@GetMapping("/book/search")
public ResponseEntity readBooks (Pageable pageable) {
        return ResponseEntity.ok(libraryService.readBooks(pageable));
}

And the most awesome thing with spring boot is, It has the capability of accepting Paginated request directly into the pageable object. So we have only to pass it into the service and repository.

Now our API is done with Pagination and Sorting,

Implementing API Endpoint With Filtering

Here we are accepting custom query from the request and adding filtering mechanism to the API.

Here I’ll demonstrate it with separate API endpoint but you can have single API endpoint to support Pagination, Filtering and Sorting.

First, add the following method into the BookRepository.java which allows reading book by name along with pagination request data. Here I’m going to read every book which contains the user-entered query in the name,

Page<Book> findAllByNameContains(String name, Pageable pageable);

Then implement service code to support filtering, Add following method to the LibraryService.java

public PaginatedBookResponse filterBooks(String name, Pageable pageable) {

        Page<Book> books = bookRepository.findAllByNameContains(name, pageable);
        return PaginatedBookResponse.builder()
                .numberOfItems(books.getTotalElements()).numberOfPages(books.getTotalPages())
                .bookList(books.getContent())
                .build();
    }

After that, setup the API endpoint to facilitate necessary implementation,

@GetMapping("/book/search/filter") 
public ResponseEntity readBooksWithFilter (@RequestParam("query") String query, Pageable pageable) {
     return ResponseEntity.ok(libraryService.filterBooks(query, pageable));
}

All done, Let’s test our API,

Testing API

  1. Pagination Request

Without binding any parameter like size and page, Here it will get default values and return the necessary data from API

http://localhost:8081/api/library/book/search

pagination request with necessary parameters.

http://localhost:8081/api/library/book/search?page=0&size=10

  1. Pagination Request with Sorting

http://localhost:8081/api/library/book/search?page=0&size=10&sort=isbn

changing sorting direction, by default this will sort in ASC order, and you can change it to DESC as follows,

http://localhost:8081/api/library/book/search?page=0&size=10&sort=id,DESC

adding multiple sorting params,

http://localhost:8081/api/library/book/search?page=0&size=10&sort=id,isbn

Here API will sort items from id and then sort the result again with isbn.

3. Pagination Request with Filtering

http://localhost:8081/api/library/book/search/filter?query=fil&page=0&size=10

Conclusion

All done, Now I hope you have a good understanding of how to build pagination-enabled rest API with spring boot plus sorting and filtering. Comment on your ideas or issues you are facing while developing your Spring boot API.

You can find source codes for this tutorial from our Github.