Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data does not handle Pageable action argument creation

I have a simple controller action:

public class CategoriesController
{
    @RequestMapping(value = { "/", "" })
    public String list(
        Model model,
        @PageableDefault(size = CategoriesController.PAGE_LIMIT) Pageable pager
    )
    {
        // load page data
        Page<Category> page = this.categoryService.findAll(pager);

        /* action logic here */
    }
}

Here is my pom.xml fragment:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>3.2.4.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>3.2.4.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>3.2.4.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons</artifactId>
        <version>1.6.4.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>1.5.0.RELEASE</version>
    </dependency>

After addtion this to my applicationContext.xml:

<bean class="org.springframework.data.web.config.SpringDataWebConfiguration"/>

I have following error:

org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.data.domain.Pageable]: Specified class is an interface

Spring Data itself works fine, JPA repositories are working. But until now I had hand-written pagination in controllers (calculating pages on my own, creating PageRequest objects by hand). I wanted to make use of Spring Data web extras, but they don't work for me for some reason... registering obsolete org.springframework.data.web.PageableArgumentResolver by hand partially made it working, but not completely, but still, I don't think this should even be a solution.

After enabling debug logger on org.springframework I see that:

01:37:33.850 [localhost-startStop-1] DEBUG org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader - Registering bean definition for @Bean method org.springframework.data.web.config.SpringDataWebConfiguration.pageableResolver()

So it's registered - any idea why it's not working?

like image 818
Rafał Wrzeszcz Avatar asked Mar 02 '14 23:03

Rafał Wrzeszcz


1 Answers

Your problem is that you are trying to mix XML configuration and Java Config based configuration. In this particular case that isn't going to work. The bean in the configuration class will be instantiated but that is it, they aren't registered to your <mvc:annotation-driven /> configuration.

You will have to add the beans manually to the ConversionService and your RequestMappingHandlerMapping. Either that our switch, at least your DispatcherServlet configuration to Java Config.

In XML you can configure additional argument-resolvers by using the <mvc:argument-resolvers /> tag. (This mimics the configuration from the SpringDataWebConfiguration).

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <ref bean="sortResolver"/>
        <ref bean="pageableResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

<bean id="sortResolver" class="org.springframework.data.web.SortHandlerMethodArgumentResolver" />
<bean id="pageableResolver" class="org.springframework.data.web.PageableHandlerMethodArgumentResolver">
    <constructor-arg ref="sortResolver" />
</bean>

However the SpringDataWebConfiguration does more then only these 2 resolvers it also registers a DomainClassConverter. If you also want to use that you need some additional configuration.

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />

<bean class="org.springframework.data.repository.support.DomainClassConverter">
   <constructor-arg ref="conversionService" />
</bean>

<mvc:annotation-driven conversion-service="conversionService">
    <mvc:argument-resolvers>
        <ref bean="sortResolver"/>
        <ref bean="pageableResolver" />
    </mvc:argument-resolvers>
</mvc:annotation-driven>

<bean id="sortResolver" class="org.springframework.data.web.SortHandlerMethodArgumentResolver" />
<bean id="pageableResolver" class="org.springframework.data.web.PageableHandlerMethodArgumentResolver">
    <constructor-arg ref="sortResolver" />
</bean>
like image 80
M. Deinum Avatar answered Oct 12 '22 13:10

M. Deinum