Sunday, June 9, 2013

No Hibernate session bound to thread

TransactionInterceptor is very useful when you want to ensure the data integrity and transaction consistency as it ensure the data from multiple tables are successfully updated to the database or rollback from the database when a fault has occured. What if I miss configure this in Spring? Take a look at the following code:
    <bean class="org.springframework.transaction.interceptor.TransactionInterceptor" id="matchTransaction">
        <property name="transactionManager">
            < ref bean="transactionManager"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="add*">PROPAGATION_REQUIRED< /prop>
            </props>
        </property>
    </bean>

    <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <idref bean="theBo"/>
                <idref bean="theDao"/>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <idref local="matchTransaction"/>
            </list>
        </property>
    </bean>
Following is the member function in my theDao class doing the update into the database:
    public void setSomethingToDb(String theNewValue) throws HibernateException {
  
    Criteria criteria = getSessionFactory().getCurrentSession().createCriteria(ThePojoBean.class);

        ...

    update(thePojoBean); // assume this statement is executing Hibernate's saveAndUpdate() API to database
    }
Take a closer look at matchTransaction bean, I have register the function start with add*. This indicates whatever function that starts with the prefix, add will be intercepted by TransactionInterceptor to ensure database transactions are successful. But if I declare a function name with the prefix set as shown above, this is a disaster during the getCurrentSession() call and it will cause the following error being thrown.
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
 at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
 at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
 at org.hauhsin.authentication.dao.impl.AuthenticationDaoImpl.fetchUsersDetailsByStatus(AuthenticationDaoImpl.java:23)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
 at $Proxy0.fetchUsersDetailsByStatus(Unknown Source)
 at org.huahsin.authentication.bo.impl.AuthenticationBoImpl.fetchUsersDetailsByStatus(AuthenticationBoImpl.java:97)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
 at $Proxy1.fetchUsersDetailsByStatus(Unknown Source)
 at org.huahsin.authentication.UsrStatusUpdService.updateUserStatus(UsrStatusUpdService.java:36)
 at org.huahsin.authentication.UsrStatusUpdService.main(UsrStatusUpdService.java:65)

No comments: