Spring Framework
Pageable
Constructor Error
Interface Implementation
Spring Data JPA

No primary or default constructor found for interface org.springframework.data.domain.Pageable

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

This error appears when Spring tries to instantiate Pageable as though it were a normal Java object. That fails because Pageable is an interface, not a concrete class with a default constructor.

In a normal Spring MVC controller, Pageable is supposed to be resolved by a dedicated argument resolver from query parameters such as page, size, and sort. If Spring instead tries to bind it like a request body or plain bean, you get the constructor error.

The Normal Controller Pattern

This is the usage Spring Data Web support is designed for:

java
1import org.springframework.data.domain.Page;
2import org.springframework.data.domain.Pageable;
3import org.springframework.web.bind.annotation.GetMapping;
4import org.springframework.web.bind.annotation.RestController;
5
6@RestController
7public class UserController {
8
9    private final UserRepository userRepository;
10
11    public UserController(UserRepository userRepository) {
12        this.userRepository = userRepository;
13    }
14
15    @GetMapping("/users")
16    public Page<User> getUsers(Pageable pageable) {
17        return userRepository.findAll(pageable);
18    }
19}

With the correct Spring configuration, a request like this works:

text
GET /users?page=0&size=20&sort=name,asc

Spring converts those query parameters into a PageRequest behind the scenes. You do not construct Pageable yourself.

Why the Error Happens

The error means that the PageableHandlerMethodArgumentResolver was not used, so Spring fell back to normal object binding. That usually happens for one of these reasons:

  • Spring Data Web support is not enabled
  • the project dependencies do not include the needed Spring Data web pieces
  • 'Pageable was placed in the wrong context, such as @RequestBody'
  • custom MVC configuration replaced the normal argument resolver setup

The last point is especially common in projects that heavily customize Spring MVC.

Do Not Use @RequestBody Pageable

One of the fastest ways to trigger this error is to annotate Pageable like a JSON body object.

java
1@PostMapping("/search")
2public Page<User> search(@RequestBody Pageable pageable) {
3    return userRepository.findAll(pageable);
4}

That tells Spring to deserialize JSON into Pageable, which is impossible because interfaces do not have constructors. Pageable is meant to come from request parameters, not from the body.

If you need a JSON request body plus pagination, separate them:

java
1@PostMapping("/search")
2public Page<User> search(@RequestBody UserSearchRequest request, Pageable pageable) {
3    return userRepository.search(request, pageable);
4}

Now the body maps to a real DTO, while pagination still comes from query parameters.

Enable Spring Data Web Support When Needed

Spring Boot usually wires pageable resolution automatically when the right Spring Data dependencies are on the classpath. In plain Spring MVC or heavily customized setups, you may need to enable it explicitly.

java
1import org.springframework.context.annotation.Configuration;
2import org.springframework.data.web.config.EnableSpringDataWebSupport;
3
4@Configuration
5@EnableSpringDataWebSupport
6public class WebConfig {
7}

That registers the argument resolvers that know how to turn query parameters into Pageable and Sort objects.

Watch Out for Custom MVC Configuration

If you extend low-level MVC configuration classes or replace parts of Spring's default web setup, you can accidentally disable the resolver that handles Pageable.

A simpler customization style is usually safer than replacing the whole MVC configuration stack. If paging suddenly breaks after a web-config refactor, check whether the pageable argument resolver is still being registered.

Default Paging Values

You can still customize defaults without giving up the interface-based controller signature.

java
1import org.springframework.data.domain.Sort;
2import org.springframework.data.web.PageableDefault;
3
4@GetMapping("/users")
5public Page<User> getUsers(
6    @PageableDefault(size = 25, sort = "name", direction = Sort.Direction.ASC)
7    Pageable pageable
8) {
9    return userRepository.findAll(pageable);
10}

This keeps the controller clean while giving predictable defaults when the client omits paging parameters.

Common Pitfalls

  • Treating Pageable like a request-body DTO instead of a query-parameter object.
  • Missing Spring Data Web support, so no argument resolver is available.
  • Custom MVC configuration that unintentionally disables pageable resolution.
  • Trying to instantiate Pageable directly instead of letting Spring create a PageRequest.
  • Mixing search-body parameters and pagination in one interface type instead of using a DTO plus Pageable separately.

Summary

  • 'Pageable is an interface, so Spring cannot construct it like a normal bean.'
  • In controllers, Pageable should usually be resolved from query parameters such as page, size, and sort.
  • Do not use @RequestBody Pageable.
  • Make sure Spring Data Web support and the pageable argument resolver are active.
  • If you need request-body filters plus pagination, use a separate DTO for the body and keep Pageable as its own method parameter.

Course illustration
Course illustration

All Rights Reserved.