Failed to instantiate Pageable bean

2020-01-31 04:58发布

问题:

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!

回答1:

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.



回答2:

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();
}


回答3:

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();


回答4:

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;
    }
}


回答5:

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?