Paginating RESTful API responses in Spring MVC
Pagination lets you split large RESTful API responses from Spring MVC into smaller chunks called pages. In this post, let us see how to use Spring MVC and Spring JPA to paginate a JSON response from a spring boot application.
Pagination and Sorting in Spring MVC
As we have seen earlier, we can implement pagination and sorting using spring data JPA. Spring MVC takes it to next level by injecting Pageable objects directly from the web layer.
Spring MVC allows you to pass the following optional query parameters to build a Pageable object on request scope. We can further use these Pageable objects in our JPA repository methods. So let’s see how to implement them.
Add Dependencies for Web and JPA
For this example, we are using Spring Data JPA and Spring Web components as dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Code language: HTML, XML (xml)
Write a Pageable JPA repository method
Next, we need to write a repository that returns database records in pages. We have seen how to write and use them in detail in our previous post. In our case, we are using an Account class.
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
String accountNumber;
String fullName;
@JsonBackReference
@ManyToOne
Branch branch;
BigDecimal balance;
// getters and setters
}
Code language: JavaScript (javascript)
public interface AccountRepository extends JpaRepository<Account, Integer> {
@Query("select a from Account a")
Page<Account> findAllAccounts(Pageable pageable);
}
Code language: PHP (php)
We will use this JPA pagination implementation in our service to pass the pageable from the Spring MVC controller.
Write a Spring MVC controller with Pageable parameter
Next, we can write an AccountService and AccountController that uses the AccountRepository interface.
@Service
public class AccountService {
private final AccountRepository accountRepository;
public AccountService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
public Page<Account> getAccounts(Pageable pageable) {
return accountRepository.findAllAccounts(pageable);
}
}
Code language: PHP (php)
Now the spring MVC controller class with pagination.
@RestController
public class AccountController {
private final AccountService accountService;
public AccountController(AccountService accountService) {
this.accountService = accountService;
}
@GetMapping("/accounts")
Page<Account> getAccounts(Pageable pageable) {
return accountService.getAccounts(pageable);
}
}
Code language: PHP (php)
As you can see, the response itself is a Page object. Let’s run the application and see how this implementation behaves.
As you see here, the response contains a content field that contains 20 of the account records. And it also comes with the current page-related metadata. From here, the clients can display total elements, number of pages, the current pages, etc in the front end.
But remember, we didn’t add any query parameters. But still, spring MVC uses pagination because, by default, spring sets the page size to 20 without any sorting.
Spring MVC pagination parameters
You can pass the following parameters to override the page behavior.
- page – Represents the Page number that you want to request (Starts at 0 and defaults to 0)
- size – Number of elements to return in the results ( Defaults to 20)
- sort – A list of strings that represent a fields to sort on. (including sort direction ASC, DESC)
So let’s check these parameters in action. To get view a specific page, you can do something like this.
http://localhost:8080/accounts?page=2
Code language: JavaScript (javascript)
If you want to specify the number of elements on a page, then you can pass the size parameter
http://localhost:8080/accounts?page=2&size=15
Code language: JavaScript (javascript)
If you decide to sort the objects by their fields, then you can pass a sort parameter with optional sort direction as well.
http://localhost:8080/accounts?page=2&size=15&sort=balance,DESC
Code language: JavaScript (javascript)
You can even sort with two fields using multiple sort parameters.
http://localhost:8080/accounts?page=2&size=15&sort=balance,DESC&sort=id,ASC
Code language: JavaScript (javascript)
Spring MVC Configurations for Pagination and sorting
Spring MVC offers certain configuration options to tweak the behavior of pagination. Here are important ones for you to know.
If your API already has a page or size parameter, then you can change the parameter names as shown below.
spring.data.web.pageable.page-parameter=chunk
spring.data.web.pageable.size-parameter=limit
You can also change the parameter names by adding a prefix to your pageable parameters.
spring.data.web.pageable.prefix=page
This way, the request should be something like /accounts?page_chunk=1&page_limit=30.
And if you prefer pages to start from 1 instead of 0, then you can use the following config.
spring.data.web.pageable.one-indexed-parameters=true
Code language: JavaScript (javascript)
Also, the size parameter can have a value up to 2000 by default. And the default page size is 20. Depending on your requirement, if you would like to increase or decrease it, then you should use the following configuration.
spring.data.web.pageable.default-page-size=30
spring.data.web.pageable.max-page-size=500
Code language: PHP (php)
Summary
To sum it up, we learned how to implement pagination in RESTful web services using Spring MVC and Spring Data JPA. You can find the above example in our GitHub repository.