Wicket in Action

Wicket/Spring/Hibernate configuration

05 June 2009, by dashorst

I like annotations and loathe oodles of XML. To get Spring and Hibernate work with those nice @Transactional, @Service and @Entity annotations by scanning your classpath, the following Spring configuration files should do the trick for your default Wicket Quickstart project (provided you add the necessary Spring and Hibernate dependencies to your setup). Figuring this out took me an evening (especially getting the scanners and @Transactional support up and running), so here"s my setup such that you don"t have to spend the evening yourself:

<?xml version="1.0" encoding="UTF-8"?>
<beans default-autowire="autodetect"
    xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <bean id="wicketApplication" class="com.mycompany.WicketApplication" />

    <bean id="placeholderConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="false" />
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="ignoreResourceNotFound" value="false" />
        <property name="locations">
            <list>
                <value>classpath*:/application.properties</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName">
            <value>${jdbc.driver}</value>
        </property>
        <property name="url">
            <value>${jdbc.url}</value>
        </property>
        <property name="username">
            <value>${jdbc.username}</value>
        </property>
        <property name="password">
            <value>${jdbc.password}</value>
        </property>
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />
    
    <!-- setup transaction manager  -->
    <bean id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

    <bean id="interceptor" class="com.mycompany.hibernate.HibernateInterceptor">
    </bean>

    <!-- hibernate session factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.connection.pool_size">5</prop>
                <prop key="hibernate.current_session_context_class">thread</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="hibernate.hibernate.cache.use_query_cache">true</prop>
            </props>
        </property>
        <property name="entityInterceptor">
            <ref bean="interceptor" />
        </property>
        <property name="packagesToScan">
            <list>
                <value>com.mycompany.entities</value>
            </list>
        </property>
    </bean>
    <context:component-scan base-package="com.mycompany" />
</beans>

This setup requires one additional file—application.properties:

jdbc.driver=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:phonebook
jdbc.username=sa
jdbc.password=
hibernate.dialect=org.hibernate.dialect.HSQLDialect

This will configure Spring and Hibernate to use an in memory HSQLDB database. You"ll need to download the HSQLDB jar for this as well. Or you can configure this to use mysql, oracle, sqlserver or postgresql. Put these files in src/main/resources.

I have to add the following dependencies to my quickstart pom to get HSQLDB, Hibernate and Spring working:

<dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-spring-annot</artifactId>
    <version>${wicket.version}</version>
</dependency>

<!-- HIBERNATE DEPENDENCIES -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate</artifactId>
    <version>3.2.6.ga</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>ejb3-persistence</artifactId>
    <version>3.3.2.Beta1</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-annotations</artifactId>
    <version>3.4.0.GA</version>
</dependency>
<dependency>
    <groupId>commons-dbcp</groupId>
    <artifactId>commons-dbcp</artifactId>
    <version>1.2.2</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring</artifactId>
    <version>2.5.6</version>
    <scope>compile</scope>
</dependency>

<!-- DATABASE DEPENDENCIES - HSQLDB -->
<dependency>
    <groupId>hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>1.8.0.7</version>
</dependency>

You"ll also have to configure the web.xml file to enable Spring and Spring"s OpenSessionInView filter.:

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>wicket-spring-hibernate</display-name>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>opensessioninview</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    </filter>

    <filter>
        <filter-name>wicket-spring-hibernate</filter-name>
        <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
        <init-param>
            <param-name>applicationFactoryClassName</param-name>
            <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
        </init-param>
        <init-param>
            <param-name>applicationClassName</param-name>
            <param-value>com.mycompany.WicketApplication</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>opensessioninview</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter-mapping>
        <filter-name>wicket-spring-hibernate</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

The world is your oister!