In this tutorial, you will learn how to implement pagination in your RESTful Web Services application built with Spring Boot. The code example below will demonstrate how to implement pagination for the API endpoint that returns a list of users.
I assume you already have your Spring Boot RESTful Web Service built, but if you are just starting, read the following tutorial that teaches how to quickly create a very simple RESTful Web Service with Spring Boot.
@RestController Class Method
In this tutorial, I will demonstrate how to implement pagination to implement a feature to return a list of users registered with my app. And since it is a RESTful Web Service, I will need to create a very simple @RestController class with at least one method which returns a list of users.
@RestController @RequestMapping("users") public class UserController { @Autowired UserService userService; @GetMapping public List<UserRest> getUsers(@RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "limit", defaultValue = "30") int limit) { List<UserRest> returnValue = new ArrayList<>(); List<UserDto> users = userService.getUsers(page, limit); for (UserDto userDto : users) { UserRest userModel = new UserRest(); BeanUtils.copyProperties(userDto, userModel); userModel.setHref("/users/" + userDto.getUserId()); returnValue.add(userModel); } return returnValue; } }
Reading Request Parameters
We implement pagination in our application because we do not want to return the entire list of records stored in our database. It might be too much data to pass over the network, and if a mobile app consumes this data, it will be very costly for an end user. We need to return the requested number of records only.
Let’s say our RESTful API is being used by a mobile app, and the view that displays the list of users can display only 25 records. Then the user needs to scroll down, and the mobile app will need to fetch the next 25 records.
To do that mobile app will need to send an HTTP GET request to our RESTful Web Service endpoint and first request 25 records for page 1 and then the next 25 records for page 2. The page number and the number of records will be passed on to our Web Service via a URL Query String Request parameters like in the example below:
http://localhost:8080/api/users?page=1&limit=25
where:
– a page is page number and,
– the limit is the number of records to return.
And for the second page, the request URL will look like this:
http://localhost:8080/api/users?page=2&limit=25
You probably already noticed how to read URL query request parameters in the code example above. Below is one more example:
@RestController @RequestMapping("users") public class UserController { @Autowired UserService userService; @GetMapping public List<UserRest> getUsers(@RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "limit", defaultValue = "30") int limit) { List<UserRest> returnValue = new ArrayList<>(); // other code here return returnValue; }
To read the page number request parameter, our method above has a page method argument with a @RequestParam annotation:
@RequestParam(value = "page", defaultValue = "0") int page
To read the limit request parameter, our method above has the limit method argument:
@RequestParam(value = "limit", defaultValue = "30") int limit
Service Class, Pageable, and PageRequest
Once the request parameters are read, they are passed on to a method in the service class that performs a bit more business logic. Below is an example of my service class and an interface that this service class implements.
public interface UserService { List<UserDto> getUsers(int page, int limit); }
@Service public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; @Override public List<UserDto> getUsers(int page, int limit) { List<UserDto> returnValue = new ArrayList<>(); Pageable pageableRequest = PageRequest.of(page, limit); Page<UserEntity> users = userRepository.findAll(pageableRequest); List<UserEntity> userEntities = users.getContent(); for (UserEntity userEntity : userEntities) { UserDto userDto = new UserDto(); BeanUtils.copyProperties(userEntity, userDto); returnValue.add(userDto); } return returnValue; } }
To load a list of records from my database(MySQL), I use Spring Data JPA. Spring Data JPA does most of the work for us. All I need to do to read a list of requests for the requested page is to create a Pageable request like so:
Pageable pageableRequest = PageRequest.of(page, limit);
and then use the Spring Data JPA repository to find all records that match the specified in the Pageable criteria.
Page<UserEntity> users = userRepository.findAll(pageableRequest); List<UserEntity> userEntities = users.getContent();
and then loop through each of the UserEntity in the List to get a list of UserDto objects, but this is already optional.
In my code, I used UserRepository class. Below is more about it.
The UserRepository and JpaRepository
I have mentioned above that I use Spring Data JPA to query the database for a list of records for the requested page. Spring Data JPA provides a list of ready-to-use methods that help us perform the CRUD operations: CREATE, READ, UPDATE and DELETE. All these operations are available if we use the CrudRepository interface from Spring Data JPA. But if we use the JpaRepository instead, we also get the paging functionality.
Below is my UserRepository interface example:
@Repository public interface UserRepository extends JpaRepository<UserEntity, Long>{ }
Notice that it is just an empty interface and all it does is extends the JpaRepository. Where
– UserEntity is the data type of my User Entity class, and
– Long is a data type of database record ID field.
Once we @Autowire the UserRepository interface into our class and call its findAll() method providing it with a Pageable object, Spring Data JPA will query the database. It will give us a list of records for the provided page.
The reason you need to extend JpaRepository for pagination to work is because it gives you access to the methods from PagingAndSortingRepository, which are the ones that enable pagination and sorting.
JpaRepository extends another interface called PagingAndSortingRepository. By extending JpaRepository, you inherit all the methods from PagingAndSortingRepository, plus some extra methods that are specific to JPA.
PagingAndSortingRepository provides methods that allow you to paginate and sort the data, such as findAll(Pageable pageable) and findAll(Sort sort). These methods take a Pageable or a Sort object as a parameter, which specify how you want to divide and order the data.
Add Spring Data JPA to Maven Project POM.XML
To create my RESTful Web Service with Spring Boot, I used Maven. Here is a link to my blog posts where you can quickly learn how to create a very simple RESTful Web Service with Spring Boot.
Once you have your project created with maven, open the pom.xml file and add the following dependency:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
Configure MySQL Database Connection
You can use any database to store and read information for your REST API. I used MySQL, and below I will share how to configure your Spring Boot project to work with MySQL database.
Add MySQL dependency to pom.xml
Open your pom.xml file and add the following MySQL dependency to the list of dependencies:
<dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> </dependency>
Add MySQL database connection details to application.properties file
For your Spring Boot application and the UserRepository interface to be able to connect to MySQL and read and write data to it, you need to provide database connection details in the application.properties file in your project. The application.properties file is located in /src/main/resources folder. Below is my application.properties file.
spring.datasource.url=jdbc:mysql://localhost:3306/photo_app spring.datasource.username=sergey spring.datasource.password=sergey spring.jpa.hibernate.ddl-auto=update
where the photo_app is the database name, I am connecting to.
And this is it! This was the last missing piece in this example demonstrating how to implement pagination in your RESTful Web Service application built with Maven and Spring Boot.
If you are interested in building RESTful Web services with Spring Boot and Spring Boot, check out my Spring Boot section of this blog. And if you enjoy learning by watching a step by step video tutorials, then check out the below list of video courses. Hopefully, one of them will be just what you need.
Great article thank you Sergey Kargopolov!
Just realized, default value for page should be “0” and not “1” .
Now getting the correct response.
Thanks.