Spring + Hibernate with annotations: No Hibernate Session bound to thread

25,513

You don't seem to have transaction configured yet... you can add the following into your Context Data Config file:-

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:advice id="txAdvice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:advisor pointcut="execution(* YOUR.PACKAGE..*.*(..))" advice-ref="txAdvice" />
</aop:config>

Change YOUR.PACKAGE to your actual package name, for example:-

execution(* com.project..*.*(..))

This is one lazy way to wrap all your methods in your project with transaction.

By the way, if you are going to lazily query your Hibernate domain objects (ex: parent.getChildren()) in your view, then I would highly suggest you to add this into your web.xml:-

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

This filter extends Hibernate session to the view.

Share:
25,513
nbarraille
Author by

nbarraille

;

Updated on July 26, 2022

Comments

  • nbarraille
    nbarraille almost 2 years

    I'm new to Spring and I was trying to create a webapp with the following stack: Apache Tomcat 7, MySQL, Spring MVC, Hibernate 3 with JPA annotations.

    I am trying to learn by following the book "Spring in Action, Third Edition" by Craig Walls.

    First, I wanted to create a page that displays some entries I manually added to my DB, but it looks like my application is not capable of creating/retrieving any Hibernate Session from my SessionFactory. Here is my root cause stack trace:

    exception
    
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:656)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    
    root cause
    
    org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
        org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
        org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
        com.nbarraille.www.dao.HibernateContactDAO.listContact(HibernateContactDAO.java:27)
        com.nbarraille.www.controllers.HomeController.showHomePage(HomeController.java:24)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:613)
        org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    

    And here are my concerned Classes/Config files:

    My HibernateDAO:

    @Repository
    public class HibernateContactDAO implements ContactDAO {
    
        private SessionFactory sessionFactory;
    
        @Autowired
        public HibernateContactDAO(SessionFactory sessionFactory){
            this.sessionFactory = sessionFactory;
        }
    
        public void addContact(Contact contact) {
            sessionFactory.getCurrentSession().save(contact);
        }
    
        public List<Contact> listContact() {
            @SuppressWarnings("unchecked")
            List<Contact> cl = sessionFactory.getCurrentSession().createQuery("from Contact").list();
            return cl;
        }
    
        public void removeContact(Integer id) {
            Contact contact = (Contact) sessionFactory.getCurrentSession().load(Contact.class, id);
            if (null != contact) {
                sessionFactory.getCurrentSession().delete(contact);
            }
    
        }
    }
    

    My Contact class:

    @Entity
    @Table(name="contacts")
    public class Contact implements Serializable {
        private static final long serialVersionUID = -5389913432051078273L;
    
        @Id
        @Column(name="id")
        @GeneratedValue
        private int id;
    
        @Column(name="first_name")
        private String firstname;
    
        @Column(name="last_name")
        private String lastname;
    
        @Column(name="email")
        private String email;
    
        @Column(name="telephone")
        private String telephone;
    
    
        // Setters/Getters
    }
    

    My Controller class:

    @Controller
    
        public class HomeController {
    
            private ContactDAO contactDAO; // I know I should pass through a service instead of accessing my DAO directly, and I usually do, but I skipped it here to simplify and try to locate the problem
    
            @Inject
            public HomeController(ContactDAO contactDAO){
                this.contactDAO = contactDAO;
            }
    
            @RequestMapping({"/", "/home"})
            public String showHomePage(Map<String,Object> model){
                model.put("contacts", contactDAO.listContact());
                return "index";
            }
        }
    

    Here is my Context Data Config file:

    <bean id="DBpropertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="/WEB-INF/jdbc.properties" />
        </bean>
    
    <bean id="dataSource" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/nbarraille" />
        <property name="username" value="root" />
        <property name="password" value="password" />
        </bean>
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="packagesToScan" value="com.nbarraille.www.core" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.show_sql">true</prop>
                </props>
            </property>
        </bean>
    
        <!-- Adds an advisor to any bean annotated with @Repository so that any platform-specific exception
             are caught and then rethrown as one of Spring's unchecked data access exceptions -->
        <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    

    Here is my Dispatcher Servlet config:

    <mvc:resources mapping="/resources/**"
                       location="/resources/" />
    
    <mvc:annotation-driven />
    
    <context:component-scan base-package="com.nbarraille.www" />
    
    <bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver" />
    
    <bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
            <property name="definitions">
                <list>
                    <value>/WEB-INF/tiles-def.xml</value>
                </list>
            </property>
        </bean>
    
        <bean id="messageSource"
            class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
            <property name="basename" value="classpath:messages" />
            <property name="defaultEncoding" value="UTF-8"/>
        </bean>
    
        <bean id="localeChangeInterceptor"
            class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
            <property name="paramName" value="lang" />
        </bean>
    
        <bean id="localeResolver"
            class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
            <property name="defaultLocale" value="en"/>
        </bean>
    

    And finally, here is my web.xml file:

    <servlet>
        <servlet-name>nbarraille</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>nbarraille</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    
     <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/nbarraille-service.xml
            /WEB-INF/nbarraille-data.xml
            /WEB-INF/nbarraille-security.xml
        </param-value>
    </context-param>
    
  • Johan Sjöberg
    Johan Sjöberg about 13 years
    Correct. Perhaps also consider using @Transactional notation on your DAO as an alternative to aop.
  • nbarraille
    nbarraille about 13 years
    Adding the filter thing got me rid of that error, thanks. What is it exactly it is doing? I didn't add the transaction support yet, as I don't know what it is.
  • limc
    limc about 13 years
    @nbarraille: That filter ensures your view layer has access to the Hibernate session. Keep in mind, you will need this filter AND transaction configured if you want your stuff to work properly. Having this filter doesn't mean you have any trasaction wrapped on each user request. Read this for more info: static.springsource.org/spring/docs/1.2.9/api/org/…