The Ecommerce API uses Spring Data’s pagination support to efficiently handle large datasets. This guide explains how to use pagination in your requests.
Pagination is implemented using Spring Data’s Pageable interface with HATEOAS links for navigation. The /products endpoint demonstrates this functionality.
Products Endpoint Implementation
@ GetMapping ( "/products" )
PagedModel < EntityModel < ProductView >> findAll ( Pageable pageable){
Page < Product > page = productRepository . findAll (pageable);
Page < ProductView > productViewPage = page . map (
ProductView ::new
);
return pagedResourceAssembler
. toModel (productViewPage);
}
Query Parameters
Control pagination using URL query parameters:
The page number to retrieve (zero-indexed)
Number of items per page. Maximum value is 50.
Sort criteria in the format property,direction (e.g., name,asc or price,desc)
Example Requests
Default Pagination
Custom Page Size
Specific Page
With Sorting
Multiple Sort Fields
curl http://localhost:8080/products
# Returns first page with 20 items
Configuration
Pagination defaults are configured in application.properties:
spring.data.web.pageable.default-page-size =20
spring.data.web.pageable.max-page-size =50
spring.data.web.pageable.default-page-size
Default number of items per page when size parameter is not specified
spring.data.web.pageable.max-page-size
Maximum allowed page size. Requests exceeding this value will be capped at 50.
The maximum page size of 50 prevents excessive data retrieval and ensures consistent API performance.
Response Structure
Paginated responses use Spring HATEOAS’s PagedModel format:
{
"_embedded" : {
"productViewList" : [
{
"id" : 1 ,
"name" : "Laptop" ,
"description" : "High-performance laptop" ,
"price" : 999.99 ,
"stockQuantity" : 50 ,
"_links" : {
"self" : {
"href" : "http://localhost:8080/products/1"
},
"products" : {
"href" : "http://localhost:8080/products"
}
}
},
{
"id" : 2 ,
"name" : "Mouse" ,
"description" : "Wireless mouse" ,
"price" : 29.99 ,
"stockQuantity" : 200 ,
"_links" : {
"self" : {
"href" : "http://localhost:8080/products/2"
},
"products" : {
"href" : "http://localhost:8080/products"
}
}
}
]
},
"_links" : {
"first" : {
"href" : "http://localhost:8080/products?page=0&size=20"
},
"self" : {
"href" : "http://localhost:8080/products?page=0&size=20"
},
"next" : {
"href" : "http://localhost:8080/products?page=1&size=20"
},
"last" : {
"href" : "http://localhost:8080/products?page=4&size=20"
}
},
"page" : {
"size" : 20 ,
"totalElements" : 100 ,
"totalPages" : 5 ,
"number" : 0
}
}
Response Fields
_embedded.productViewList
Array of product objects on the current page
HATEOAS navigation links for pagination:
first: First page
self: Current page
next: Next page (if available)
prev: Previous page (if available)
last: Last page
Total number of items across all pages
Current page number (zero-indexed)
HATEOAS Links
The API uses Hypermedia as the Engine of Application State (HATEOAS) to provide navigation links:
Access First Page
Start with the default endpoint: curl http://localhost:8080/products
Navigate Using Links
Use the next link from the response to get the next page: curl "http://localhost:8080/products?page=1&size=20"
Jump to Last Page
Use the last link to jump directly to the final page: curl "http://localhost:8080/products?page=4&size=20"
HATEOAS links allow clients to navigate without hardcoding URLs. Always use the provided links for pagination navigation.
Handling Edge Cases
Empty Results
When no products exist, the API returns an empty page:
{
"_embedded" : {
"productViewList" : []
},
"_links" : {
"self" : {
"href" : "http://localhost:8080/products?page=0&size=20"
}
},
"page" : {
"size" : 20 ,
"totalElements" : 0 ,
"totalPages" : 0 ,
"number" : 0
}
}
Page Out of Range
Requesting a page beyond the total pages returns an empty result:
curl "http://localhost:8080/products?page=999"
{
"_embedded" : {
"productViewList" : []
},
"page" : {
"size" : 20 ,
"totalElements" : 100 ,
"totalPages" : 5 ,
"number" : 999
}
}
Always check totalPages to avoid requesting pages that don’t exist.
Size Exceeds Maximum
Requesting a size greater than 50 will be capped:
curl "http://localhost:8080/products?size=100"
# Returns 50 items (maximum allowed)
Best Practices
Use Appropriate Page Sizes
Balance between performance and user experience:
Mobile apps: 10-20 items
Web applications: 20-50 items
Data exports: Maximum allowed (50)
Implement Client-Side Caching
Cache pages to reduce API calls: const pageCache = new Map ();
async function fetchPage ( pageNumber ) {
if ( pageCache . has ( pageNumber )) {
return pageCache . get ( pageNumber );
}
const response = await fetch (
`http://localhost:8080/products?page= ${ pageNumber } `
);
const data = await response . json ();
pageCache . set ( pageNumber , data );
return data ;
}
Handle Navigation Links
Always use HATEOAS links instead of constructing URLs: async function getNextPage ( currentPageData ) {
if ( currentPageData . _links . next ) {
const response = await fetch ( currentPageData . _links . next . href );
return await response . json ();
}
return null ; // No more pages
}
Display Total Count
Show users the total number of items: const totalItems = response . page . totalElements ;
console . log ( `Showing ${ items . length } of ${ totalItems } products` );
Sorting Options
Combine pagination with sorting for powerful data retrieval:
Sort Parameter Description Example sort=name,ascSort by name ascending A-Z sort=name,descSort by name descending Z-A sort=price,ascSort by price ascending Lowest first sort=price,descSort by price descending Highest first sort=createdAt,descSort by creation date Newest first sort=stockQuantity,ascSort by stock Lowest stock first
Multiple Sort Fields
curl "http://localhost:8080/products?sort=stockQuantity,asc&sort=price,desc"
This sorts by stock quantity (ascending), then by price (descending) for items with the same stock.
Next Steps
Products API View detailed product endpoint documentation
Error Handling Learn how pagination errors are handled