Hi all,
I have a JSF web application utilizing Hibernate. It runs with the OpenSessionInViewFilter, which works perfectly fine for my needs.
In my applicationContext.xml, I have a plain DataSource, a SessionFactory and some bean definitions. Nothing special about that (really!).
MyDao.java looks something like this:Code:<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jdbc/foo"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan"> <list> <value>foo.entities</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> </props> </property> </bean> <tx:advice id="myAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="create" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="delete" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="save" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="*" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="myPointcut" expression="execution(* foo.dao.*.*(..))"/> <aop:advisor advice-ref="myAdvice" pointcut-ref="myPointcut"/> </aop:config> <bean id="myTransactionInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="myDao" class="foo.MyDao"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
This works fine and Spring gives me Hibernate access through the same Hibernate session in each HTTP request. (Nice!)Code:public class MyDao { private SessionFactory sessionFactory; public MyEntity findById(Long id) { return (MyEntity) sessionFactory.getCurrentSession().get(MyEntity.class, id); } public List<MyEntity> getAllMyEntities { Query q = sessionFactory.getCurrentSession().getNamedQuery("MyEntity.getAllMyEntities"); return q.list(); } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }
----
What makes things funny is this:
In the same web application, I have created a context listener, which is executed by the container (Tomcat 6) on application startup. This context listener looks into Spring and creates a java.util.Timer object for each entity. I.e. something like this:
This creates a number of threads, which runs inside the application. What makes things go bad is that I cannot seem to have each thread bind its own Session to Hibernate.Code:MyDao myDao = (MyDao) WebApplicationContextUtils.getWebApplicationContext(context).getBean("myDao"); List<Timer> serverTimers = new ArrayList<Timer>(); List<MyDao> myEntities = myDao().getAllMyEntities(); for (MyEntity myEntity : myEntities) { Timer t = new Timer("Timer " + myEntity.getId()); ServerTimerTask serverTimerTask = new ServerTimerTask(myEntity.getId()); t.schedule(serverTimerTask, 5000, 20000); serverTimers.add(t); }
I have tried this inside each thread:
However this doesn't seem to work, and the threads closes sessions belonging to other threads. (Seems like a concurrency issue!)Code:TransactionSynchronizationManager.initSynchronization(); Session session = SessionFactoryUtils.getSession(sessionFactory, true); TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); // Do lots and lots of Hibernate/Dao stuff.... TransactionSynchronizationManager.unbindResource(session.getSessionFactory()); SessionFactoryUtils.closeSession(session); TransactionSynchronizationManager.clearSynchronization();
Does anyone have a clue on how to register long Hibernate sessions in SpringSessionContext so the above code will just run inside one single Hibernate session?
Best regards,
Morten
![]()


Reply With Quote
