https://github.com/spring-projects/spring-boot/blob/ca0de4385c01cbbd120e96ec9f83427fb48c9a15/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/web/SpringDataWebAutoConfiguration.java#L54

Comment From: wilkinsona

Thanks for the report, but I'm not sure that your analysis is correct. The PageableHandlerMethodArgumentResolverCustomizer is consumed by org.springframework.data.web.config.SpringDataWebConfiguration which is imported via @EnableSpringDataWebConfiguration with which SpringDataWebAutoConfiguration is annotated. I'm not sure that RepositoryRestMvcAutoConfiguration is relevant. I may be wrong, of course.

It sounds like the problem you're facing is that configuration of spring.data.web.pageable isn't working. Can you please provide a minimal sample that reproduces that problem? That will allow us to figure out exactly what the cause is and be confident that we're fixing the problem that you're having.

Comment From: jimlgx

I found it through debugging,In SpringDataWebConfiguration that private @Autowired Optional<PageableHandlerMethodArgumentResolverCustomizer> pageableResolverCustomizer; the value is null,No injection succeeds,I can write a unit test later

Comment From: wilkinsona

I can write a unit test later

Thanks. Either a unit test or a small sample that reproduces the problem will give us what we need to make some progress on this one.

Comment From: jimlgx

Referring to the demo you provided _public void customizePageable() I have modified it Please refer to the unit tests below to illustrate the problem and hopefully help you

@RunWith(SpringRunner.class)
@SpringBootTest
@EnableConfigurationProperties(value = {SpringDataWebProperties.class})
public class SpringDataWebTest {
    @Autowired
    private ApplicationContext context;

    @Autowired
    private SpringDataWebProperties properties;

    @Test
    public void customizePageableWithConfig() {
        PageableHandlerMethodArgumentResolver argumentResolver = this.context
                .getBean(PageableHandlerMethodArgumentResolver.class);
        // properties.pageable  equal to properties config
        assertThat(properties.getPageable().getPageParameter())
                .isEqualTo("p");
        assertThat(properties.getPageable().getSizeParameter())
                .isEqualTo("s");
        assertThat(properties.getPageable().isOneIndexedParameters())
                .isEqualTo(true);
        assertThat(properties.getPageable().getPrefix())
                .isEqualTo("abc");
        assertThat(properties.getPageable().getQualifierDelimiter())
                .isEqualTo("__");

        assertThat(properties.getPageable().getMaxPageSize())
                .isEqualTo(100);


        // properties.pageable not equal argumentResolver
        assertThat(ReflectionTestUtils.getField(argumentResolver, "pageParameterName"))
                .isNotEqualTo(properties.getPageable().getPageParameter());
        assertThat(ReflectionTestUtils.getField(argumentResolver, "sizeParameterName"))
                .isNotEqualTo(properties.getPageable().getSizeParameter());
        assertThat(ReflectionTestUtils.getField(argumentResolver, "oneIndexedParameters"))
                .isNotEqualTo(properties.getPageable().isOneIndexedParameters());
        assertThat(ReflectionTestUtils.getField(argumentResolver, "prefix"))
                .isNotEqualTo(properties.getPageable().getPrefix());
        assertThat(ReflectionTestUtils.getField(argumentResolver, "qualifierDelimiter"))
                .isNotEqualTo(properties.getPageable().getQualifierDelimiter());

        assertThat(ReflectionTestUtils.getField(argumentResolver, "maxPageSize"))
                .isNotEqualTo(properties.getPageable().getMaxPageSize());
    }
spring.data.web.pageable.page-parameter=p
spring.data.web.pageable.size-parameter=s
spring.data.web.pageable.default-page-size=10
spring.data.web.pageable.prefix=abc
spring.data.web.pageable.qualifier-delimiter=__
spring.data.web.pageable.max-page-size=100
spring.data.web.pageable.one-indexed-parameters=true`

https://github.com/jimlgx/spring-boot-demo/blob/master/src/test/java/com/example/springbootdemo/SpringDataWebTest.java

Comment From: wilkinsona

Thanks again. I can see the problem now. It is indeed due to some interaction between RespositoryRestMvcAutoConfiguration and SpringDataWebAutoConfiguration but the solution isn't as simple as reversing their ordering.

Our current test passes as it tests SpringDataWebAutoConfiguration in isolation. It's testing a scenario where Spring Data REST isn't on the classpath. If Spring Data REST is on the classpath, then RespositoryRestMvcAutoConfiguration comes into play. When it goes before SpringDataWebAutoConfiguration, SpringDataWebAutoConfiguration backs off due to it being conditional on a missing PageableHandlerMethodArgumentResolver which is defined by RepositoryRestMvcConfiguration (an import of RespositoryRestMvcAutoConfiguration). This backing off means that the beans that customise both paging and sorting are lost. I believe we also lose some other functionality that's imported via @EnableSpringDataWebSupport. If the order is reversed and SpringDataWebAutoConfiguration goes first then several beans are overridden causing a failure on master where bean overriding is no longer permitted.

When SpringDataWebAutoConfiguration backs off, we lose its @EnableSpringDataWebSupport in favour of an import of RepositoryRestMvcConfiguration. RepositoryRestMvcConfiguration is a subclass of HateoasAwareSpringDataWebConfiguration which is some of what @EnableSpringDataWebSupport imports. It's not yet clear to me how to fix this such that the customisation of both paging and sorting is retained while also retaining all of the functionality enabled by @EnableSpringDataWebSupport.

Comment From: wilkinsona

It isn't possible to fix this in Spring Boot due to the way in which Spring Data is structured.

If you're using Spring Data REST, then org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration.pageableResolver() is the method that will create the PageableHandlerMethodArgumentResolver. It calls its super method to create and customise the resolver using a PageableHandlerMethodArgumentResolverCustomizer which applies the spring.data.web.pageable properties. They are then immediately overwritten based on the RepositoryRestConfiguration. In Spring Boot, RepositoryRestConfiguration can be customised using the spring.data.rest properties.

In short, if you are using Spring Data REST then you need to use the spring.data.rest properties, if you are just using Spring Data's Web support without Spring Data REST, then you need to use the spring.data.web.pageable properties. This isn't ideal, but is the best that we can do given Spring Data's current architecture.

I think we should open a Spring Data issue and turn this into a documentation issue.

Comment From: wilkinsona

I've opened DATAREST-1290.

Comment From: RoonyLi

@Configuration
public class PageableConfig {

    @Bean
    PageableHandlerMethodArgumentResolverCustomizer pageableResolverCustomizer() {
        return pageableResolver -> pageableResolver.setOneIndexedParameters(true);
    }
}

it will work

Comment From: RoonyLi

i think the SpringDataWebAutoConfiguration should remove @ConditionalOnMissingBean(PageableHandlerMethodArgumentResolver.class) @wilkinsona

Comment From: wilkinsona

Thanks for the suggestion but we can't do that as it may result in multiple PageableHandlerMethodArgumentResolverCustomizer beans and Spring Data requires there to be at most one (or for one to be @Primary).

Comment From: ghost

@All - Is this resolved ? What's the better alternative for this?

Comment From: wilkinsona

@JavaHelper We’ve done all we can in Boot by documenting Spring Data REST’s quirks. If this problem is important to you, please vote for or comment on DATAREST-1290 and let them know.

Comment From: zhangalex

@Configuration
public class PageableConfig {

    @Bean
    PageableHandlerMethodArgumentResolverCustomizer pageableResolverCustomizer() {
        return pageableResolver -> pageableResolver.setOneIndexedParameters(true);
    }
}

This is the best solution.

Comment From: wilkinsona

@gopalsingh462 If you are using Spring Data REST, that is to be expected. This is explained above:

They are then immediately overwritten based on the RepositoryRestConfiguration.

Please follow this advice:

In short, if you are using Spring Data REST then you need to use the spring.data.rest properties, if you are just using Spring Data's Web support without Spring Data REST, then you need to use the spring.data.web.pageable properties. This isn't ideal, but is the best that we can do given Spring Data's current architecture.

Comment From: wilkinsona

I suspect you're not using Spring Data REST so you should set spring.data.web.pageable.one-indexed-parameters=true in your application.properties file.

If you have any further questions, please follow up on Stack Overflow or Gitter. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.