20

I use Spring 4.1.6.RELEASE and Spring Data Jpa 1.8.0.RELEASE. I have a problem with org.springframework.data.domain.Pageable bean creation. It is used in my controller:

@Controller
public class ItemsController {

    @Autowired
    ProductService itemsService;

    @RequestMapping(value = "/openItemsPage")
    public String openItemsPage() {
        return "items";
    }

    @RequestMapping(value = "/getItems", method = RequestMethod.GET)
    @ResponseBody
    public Item[] getItems(Pageable pageable) {

        return itemsService.getItems(pageable);
    }
}

Also I have a next xml configurations in my application context:

<context:component-scan base-package="com.mobox.controller" />

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <beans:bean id="sortResolver"
                class="org.springframework.data.web.SortHandlerMethodArgumentResolver" />
        <beans:bean
                class="org.springframework.data.web.PageableHandlerMethodArgumentResolver">
            <beans:constructor-arg ref="sortResolver" />
        </beans:bean>
    </mvc:argument-resolvers>
</mvc:annotation-driven>

And finaly I do A next requsr from the client:

   $.ajax({
        type: "GET",
        url: "getProducts?page=0&size=100",
        .....

In tomcat log I see next:

    SEVERE: Servlet.service() for servlet [appServlet] in context with path [/a2delivery-web] threw exception [Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.domain.Pageable]: Specified class is an interface] with root cause
org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.domain.Pageable]: Specified class is an interface
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:101)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:80)
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:106)
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77)
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
    ....................

Please help me to resolve this issue, thanks!

Dimon
  • 763
  • 3
  • 7
  • 22

5 Answers5

27

The easiest way to get this working is to set @EnableSpringDataWebSupport in your configuration. Alternatively, in a pure XML based configuration, declare SpringDataWebConfiguration as Spring bean.

That will make sure the necessary HandlerMethodArgumentResolver will be registered correctly.

Oliver Drotbohm
  • 80,157
  • 18
  • 225
  • 211
  • Thank you, seems you are right, but steel problem is actual. In stacktrace I see that HandlerMethodArgumentResolverComposite class is do a job: for actual MethodParameter parameter with "parametrType" org.springframework.data.domain.Pageable it should get PageableHandlerMethodArgumentResolver, but in my case It is getting org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor, why? – Dimon May 06 '15 at 13:27
  • Seems like your Spring MVC configuration customization is not applied. – Oliver Drotbohm May 07 '15 at 13:27
  • 1
    Works when all configured as java based configuration, but when I am mixing xml and java based confs - not. For xml configuratiion works the next solution: http://stackoverflow.com/questions/22135002/spring-data-does-not-handle-pageable-action-argument-creation – Dimon May 09 '15 at 13:07
  • 1
    @EnableSpringDataWebSupport pulls in a new Configuration class that extends WebMvcConfigurerAdapter. It possibly overwrites your configuration - or vice-versa. – Jan Apr 06 '16 at 10:46
  • 1
    Had this problem in a `@WebMvcTest`. Adding `@EnableSpringDataWebSupport` to my inner `@TestConfiguration` class solved it. – Wim Deblauwe Jan 20 '17 at 12:59
21

Add the following to you're test class:

@Inject
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;

PageableHandlerMethodArgumentResolver

and configure it during MockMvc setup:

@Before
public void setup() {
    ...
    this.mockMvc = MockMvcBuilders.standaloneSetup(resource)
        .setCustomArgumentResolvers(pageableArgumentResolver)
        .build();
}
Tom Van Rossom
  • 1,440
  • 10
  • 18
4

just to add on to Tom Van Rossom's reply, if you use @RunWith(MockitoJUnitRunner.class), you can create an instance of PageableHandlerMethodArgumentResolver when you initialize the mockMvc (like what Loren mentioned).Eg

mockMvc = MockMvcBuilders.standaloneSetup(restController)
            .setCustomArgumentResolvers(new PageableHandlerMethodArgumentResolver())
            .build();
mengjiann
  • 275
  • 3
  • 12
0

Alternative way besides other answers which might work for you.

@Configuration
@ComponentScan(basePackages = {"my.package1", "my.package2"})
@EnableWebMvc
public class SpringMVCRestConfiguration extends WebMvcConfigurerAdapter {

    //Adding the resolver for Pagination and Sorting Resolver
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(paginationResolver());
        argumentResolvers.add(sortResolver());
    }

    //Inject the sortResolver
    @Bean
    public SortHandlerMethodArgumentResolver sortResolver() {
        SortHandlerMethodArgumentResolver argumentResolver = new SortHandlerMethodArgumentResolver();
        return argumentResolver;
    }

    //Inject the Pagination Resolver
    @Bean
    public PageableHandlerMethodArgumentResolver paginationResolver() {
        PageableHandlerMethodArgumentResolver argumentResolver = new PageableHandlerMethodArgumentResolver();
        argumentResolver.setMaxPageSize(10);
        argumentResolver.setOneIndexedParameters(true);
        return argumentResolver;
    }
}
Mehdi
  • 3,795
  • 3
  • 36
  • 65
-2

Pageable used in the getItems method is an interface and spring will not be able to instantiate it.

You can either

  1. Provide an Java bean style implementation of Pageable and used that instead of Pageable in the getItems method.
  2. Or use the ModelAttribute to create a Pageable object(for example, PageRequest). Here is a link for more details on ModelAttribute: What is @ModelAttribute in Spring MVC?
Community
  • 1
  • 1
yunbugg
  • 37
  • 3