akeyla
Jun 30th, 2009, 09:37 AM
Hi,
We have legacy Hibernate 2.1 code wherein we used a custom "session per transaction" pattern. We are on Jboss 4.2.0 and the code works perfectly when used within EJBs. In the openSession() call, we go and get the associated transaction and the assign a SessionSynchronization object to the session. On commit, the session is flushed and closed, on rollback the session is closed without flush. Relevant code portions are attached
/** Get the current JTA transaction */
private static javax.transaction.Transaction getCurrentTransaction(SessionFactory sessionFactory)
throws SystemException
{
javax.transaction.Transaction trans = null;
SessionFactoryImplementor sessionFactoryImpl = (SessionFactoryImplementor)sessionFactory;
if (sessionFactoryImpl != null)
{
TransactionManager txManager = sessionFactoryImpl.getTransactionManager();
if (txManager != null)
{
trans = txManager.getTransaction();
}
}
return trans;
}
Once transaction has been obtained, register a synchronization object with the transaction. Note that the code associated with the association of session and transaction in a hashmap for future lookups of session based on transaction is excluded, the code below refers to when a new transaction is encountered.
Synchronization synch = new SessionSynchronization(domainObjectClass, t);
if (t != null)
{
t.registerSynchronization(synch);
map.put(t, s);
threadTxnSession.set(map);
}
This code works flawlessly in an EJB context. When a method is called (that has a transaction semantic), the synchronization object is created and when the method exits properly the transaction is committed and session is flushed and closed and if there is a RuntimeException, the transaction is rolled back and the session is cliosed without flushing.
The hibernate cfg.xml file has
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory name="jdbc.datasource.MortracBravuraDataSource.hbm">
<!-- properties -->
<property name="connection.datasource">jdbc.datasource.MortracBravuraDataSource</property>
<property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>
<property name="hibernate.transaction.factory_class">net.sf.hibernate.transaction.JTATransactionFactory</property>
<property name="jta.UserTransaction">UserTransaction</property>
<property name="transaction.manager_lookup_class">net.sf.hibernate.transaction.JBossTransactionManag erLookup</property>
<property name="use_outer_join">true</property>
<property name="show_sql">true</property>
<property name="format_sql">false</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="interceptor">com.fsb.framework.persistence.HibernateInterceptor</property>
<!-- mapping files -->
<mapping resource="com/fsb/domain/ajax/ZipCode.hbm.xml"/>
<mapping resource="com/fsb/domain/Country.hbm.xml"/>
<mapping resource="com/fsb/domain/HBM_IncomeDetail.hbm.xml"/>
<!-- OTHER MAPPINGS -->
</session-factory>
</hibernate-configuration>
Now we want to reuse the same Hibernate code within a war and rather than going with EJBs we are hoping to replicate the Transactional behaviour using Spring @Transactional. We are using Spring 2.5.1. The methods are annotated with @Transactional and in the applicationContext-jta.xml file, we have
<!-- We want to use Spring's declarative @Transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Run Time Txn Manager Bean -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransaction Manager">
<property name="transactionManagerName" value="java:/TransactionManager"></property>
<property name="userTransactionName" value="java:comp/UserTransaction"></property>
</bean>
More info in next post.
Any help in this matter is appreciated. Our assumption is that we are missing some small thing. If you need any more information, I will be glad to provide it.
Regards
Sandesh
We have legacy Hibernate 2.1 code wherein we used a custom "session per transaction" pattern. We are on Jboss 4.2.0 and the code works perfectly when used within EJBs. In the openSession() call, we go and get the associated transaction and the assign a SessionSynchronization object to the session. On commit, the session is flushed and closed, on rollback the session is closed without flush. Relevant code portions are attached
/** Get the current JTA transaction */
private static javax.transaction.Transaction getCurrentTransaction(SessionFactory sessionFactory)
throws SystemException
{
javax.transaction.Transaction trans = null;
SessionFactoryImplementor sessionFactoryImpl = (SessionFactoryImplementor)sessionFactory;
if (sessionFactoryImpl != null)
{
TransactionManager txManager = sessionFactoryImpl.getTransactionManager();
if (txManager != null)
{
trans = txManager.getTransaction();
}
}
return trans;
}
Once transaction has been obtained, register a synchronization object with the transaction. Note that the code associated with the association of session and transaction in a hashmap for future lookups of session based on transaction is excluded, the code below refers to when a new transaction is encountered.
Synchronization synch = new SessionSynchronization(domainObjectClass, t);
if (t != null)
{
t.registerSynchronization(synch);
map.put(t, s);
threadTxnSession.set(map);
}
This code works flawlessly in an EJB context. When a method is called (that has a transaction semantic), the synchronization object is created and when the method exits properly the transaction is committed and session is flushed and closed and if there is a RuntimeException, the transaction is rolled back and the session is cliosed without flushing.
The hibernate cfg.xml file has
<hibernate-configuration>
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory name="jdbc.datasource.MortracBravuraDataSource.hbm">
<!-- properties -->
<property name="connection.datasource">jdbc.datasource.MortracBravuraDataSource</property>
<property name="dialect">net.sf.hibernate.dialect.OracleDialect</property>
<property name="hibernate.transaction.factory_class">net.sf.hibernate.transaction.JTATransactionFactory</property>
<property name="jta.UserTransaction">UserTransaction</property>
<property name="transaction.manager_lookup_class">net.sf.hibernate.transaction.JBossTransactionManag erLookup</property>
<property name="use_outer_join">true</property>
<property name="show_sql">true</property>
<property name="format_sql">false</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="interceptor">com.fsb.framework.persistence.HibernateInterceptor</property>
<!-- mapping files -->
<mapping resource="com/fsb/domain/ajax/ZipCode.hbm.xml"/>
<mapping resource="com/fsb/domain/Country.hbm.xml"/>
<mapping resource="com/fsb/domain/HBM_IncomeDetail.hbm.xml"/>
<!-- OTHER MAPPINGS -->
</session-factory>
</hibernate-configuration>
Now we want to reuse the same Hibernate code within a war and rather than going with EJBs we are hoping to replicate the Transactional behaviour using Spring @Transactional. We are using Spring 2.5.1. The methods are annotated with @Transactional and in the applicationContext-jta.xml file, we have
<!-- We want to use Spring's declarative @Transaction management -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Run Time Txn Manager Bean -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransaction Manager">
<property name="transactionManagerName" value="java:/TransactionManager"></property>
<property name="userTransactionName" value="java:comp/UserTransaction"></property>
</bean>
More info in next post.
Any help in this matter is appreciated. Our assumption is that we are missing some small thing. If you need any more information, I will be glad to provide it.
Regards
Sandesh