2

I am using Hibernate's lazy loading, and am getting sessionFactory missing exception, even after I have defined a filter in web.xml to use OpenSessionInViewFilter

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>
       org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping> 
</web-app>

My servlet-context.xml has following session and transaction manager definitions:

<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource"/>
    <beans:property name="hibernateProperties">
        <beans:props>
            <beans:prop key="hibernate.dialect">${connection.dialect}</beans:prop>
            <beans:prop key="hibernate.show_sql">true</beans:prop>
       </beans:props>
    </beans:property>
    <beans:property name="annotatedClasses">
        <beans:list>
            <beans:value>example.EntityA</beans:value>
            <beans:value>example.EntityB</beans:value>
        </beans:list>
    </beans:property>
</beans:bean>

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

I still get the following exception:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'sessionFactory' is defined

I have tried defining a sessionFactoryBeanName attribute but results don't change. What am I doing wrong?

Loke
  • 249
  • 1
  • 6
  • 14

3 Answers3

3

You need to declare sessionFactory in the root web application context (i. e. /WEB-INF/spring/root-context.xml) to make it available to OpenSessionInViewFilter.

axtavt
  • 239,438
  • 41
  • 511
  • 482
  • This works. Is there a way to bring all the filter settings to servlet-context.xml as well, thus not having to define sessionfactory in root-context.xml? Thanks – Loke Dec 20 '11 at 11:51
  • @Loke: No. `OpenSessionInViewFilter` is invoked before request reaches servlet, therefore filter cannot access servlet-specific stuff. – axtavt Dec 20 '11 at 11:54
0

This is the code fragment inside the org.springframework.orm.hibernate3.support.OpenSessionInViewFilter class that looks up the sessionFactory bean :

/**
 * Look up the SessionFactory that this filter should use.
 * <p>The default implementation looks for a bean with the specified name
 * in Spring's root application context.
 * @return the SessionFactory to use
 * @see #getSessionFactoryBeanName
 */
protected SessionFactory lookupSessionFactory() {
    if (logger.isDebugEnabled()) {
        logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + "' for OpenSessionInViewFilter");
    }
    WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
    return wac.getBean(getSessionFactoryBeanName(), SessionFactory.class);
}

You'll notice that it uses the WebApplicationContextUtils class to load the session factory bean. The API (http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/support/WebApplicationContextUtils.html) for this class states :

Convenience methods for retrieving the root WebApplicationContext for a given ServletContext. This is useful for programmatically accessing a Spring application context from within custom web views or MVC actions.

Note that there are more convenient ways of accessing the root context for many web frameworks, either part of Spring or available as an external library. This helper class is just the most generic way to access the root context.

Thus you are required to declare the sessionFactory in the root context if you wish to use the Spring provided OpenSessionInViewFilter feature out of the box.

Suketu Bhuta
  • 1,871
  • 1
  • 18
  • 26
0

You have to put sesstionFactory Bean in your servlet-context.xml

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="annotatedClasses">
    .....
</property>
<property name="hibernateProperties">
    ......
</property>
<property name="schemaUpdate" value="true" />

Boni
  • 590
  • 1
  • 3
  • 11
  • My session-Factory is already **in** servlet-context.xml. As @axtavt suggested, I could fix it by defining sessionFactory in root-context.xml. If you are able to keep sessionFactory in servlet-context.xml, would you share your filter definitions, and the file in which you define them? – Loke Dec 20 '11 at 11:56