Eric Smith
Eric Smith

Reputation: 178

Upgrade from Spring Boot 1.3 to Spring Boot 1.4 and Pageable is not working as expected.

I am converting an existing Spring Boot application from 1.3.6 to 1.4.1. I would like to have a default page size for repository and controller responses of 25. I am not getting the expected behavior in either case. For repository methods I am getting a page size of 20. For controllers I am getting 0 for the page size.

I added a new configuration class to define the default page size. I found this code snippet in another article. The debug message does get printed out.

@Configuration
public class RestConfigurationAdapter extends WebMvcConfigurerAdapter {

    private static final int DEFAULT_PAGE_SIZE = 25;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        System.out.println("DEBUG: AddArguments----");
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
        resolver.setFallbackPageable(new PageRequest(0, DEFAULT_PAGE_SIZE));
        argumentResolvers.add(resolver);
        super.addArgumentResolvers(argumentResolvers);
    }


}

In a custom controller I would like to have a default pageable populated with a size of 25. However the pageable object is null in this controller. In 1.3.x the pageable object worked as expected.

public class BatchManagerController
{
    @Autowired
    private BatchRepository batchRepository;

    @Autowired
    private PagedResourcesAssembler pagedResourcesAssembler;

    @Transactional(readOnly = true)
    @RequestMapping(value = "/search/managerBatchView", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    @PreAuthorize("hasRole(T(com.nextgearcapital.tms.api.util.AuthorityEnum).MANAGER)")
    public ResponseEntity<?> getManagerBatchListView(BatchListSearchRequest requestDTO, Pageable pageable, PersistentEntityResourceAssembler myAssembler)
    {
        System.out.println("DEBUG1:---------- " + pageable);
        Page<Batch> batchPage = batchRepository.findBatchesForManager(requestDTO, pageable);
        PagedResources<VaultResource> pagedResources = pagedResourcesAssembler.toResource(batchPage, myAssembler);
        return new ResponseEntity<>(pagedResources, HttpStatus.OK);
    }
}

When calling SDR Repository methods with a pageable parameter, the parameter works correctly, but it has a default page size of 20, rather than 25.

I would appreciate any help and advise in getting the correct configuration for pagination.

Upvotes: 0

Views: 1320

Answers (2)

Snekse
Snekse

Reputation: 15789

Starting in spring-data-commons version 2.0, there is are 2 new classes that might make this kind of thing easier:

  • SortHandlerMethodArgumentResolverCustomizer
  • PageableHandlerMethodArgumentResolverCustomizer

Unfortunately that's not the version that ships with the current version (1.5.9) of Spring Boot, so replace at your own risk.

@Bean 
PageableHandlerMethodArgumentResolverCustomizer pagingCustomizer() {
    // p is PageableHandlerMethodArgumentResolver
    return p -> p.setMaxPageSize(25);
}

In this case, one would probably call resolveArgument to manipulate it.

That said, I'm not sure spring-data-rest would use that config. There is a HateoasPageableHandlerMethodArgumentResolver which seems more likely that source of what I would think SDR would use. If that's the case, the BeanPostProcessor @M. Deinum suggested is probably your best option.

Spring Data Web Support

Upvotes: 0

M. Deinum
M. Deinum

Reputation: 124506

You probably have 2 solutions

  1. Register the PageableHandlerMethodArgumentResolver as an @Bean which will disable the auto configuration for Spring Data Web.
  2. Create a BeanPostProcessor to do additional configuration on the existing PageableHandlerMethodArgumentResolver.

Using @Bean

@Configuration
public class RestConfigurationAdapter extends WebMvcConfigurerAdapter {

    private static final int DEFAULT_PAGE_SIZE = 25;

    @Bean
    public PageableHandlerMethodArgumentResolver pageableResolver() {
        PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
        resolver.setFallbackPageable(new PageRequest(0, DEFAULT_PAGE_SIZE));
        return resolver;
   }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        System.out.println("DEBUG: AddArguments----");
        argumentResolvers.add(pageableResolver());
    }
}

Drawback is that it will disable the autoconfiguration for Spring Data Web, so you might miss some things.

Using a BeanPostProcessor.

@Bean
public BeanPostProcessor pageableProcessor() {

    private static final int DEFAULT_PAGE_SIZE = 25;

    return new BeanPostProcessor() {
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof PageableHandlerMethodArgumentResolver) {
                ((PageableHandlerMethodArgumentResolver) bean).setFallbackPageable(new PageRequest(0, DEFAULT_PAGE_SIZE));
            }
            return bean;
        }

        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
}

Drawback is that it is a little more complex as registering your own PageableHandlerMethodArgumentResolver instance as a bean. Advantage however is that you can simply use this to add additional configuration to existing beans and leave the auto configuration in tact.

Upvotes: 1

Related Questions