Announcement Announcement Module
Collapse
No announcement yet.
Problem with JTA transaction rollback Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem with JTA transaction rollback

    I am developing an application using JSF + Spring + Hibernate as persistence mechanism (on MySql). I am using Glassfish 2.1 as an application server. I am trying to use org.springframework.transaction.jta.JtaTransaction Manager as an implementation of transaction mechanizm but the rollback of the transactions is not happening properly. (The problem is gone when I am switching for example to HibernateTransactionManager).

    I am attaching very sample code + configuration to show the problem.

    Te bean defined below is injected to backing bean witch is calling for the save method.
    Code:
    package pl.test;
    
    imports...
    
    @Repository
    @Transactional
    public class MyRepository {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        public <T> void save(T entity) {
            Session s = sessionFactory.getCurrentSession();
            System.out.println("before save");
            s.save(entity);
            throw new RuntimeException();
        }
    ...
    }
    Context configuration

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
    
        <context:annotation-config/>
        <context:component-scan base-package="pl"/>
    
        <jee:jndi-lookup id="dataSource" jndi-name="jdbc/greatEnglish" />
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="configLocation" value="WEB-INF/hibernate.cfg.xml" />
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.hbm2ddl.auto">create</prop>
                </props>
            </property>
        </bean>
    
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <jee:jndi-lookup id="platformTransactionManager"
            jndi-name="java:appserver/TransactionManager"
            resource-ref="false"
            expected-type="javax.transaction.TransactionManager"/>
    
        <bean id="transactionManager"
            class="org.springframework.transaction.jta.JtaTransactionManager">       
            <constructor-arg ref="platformTransactionManager"/>
            <property name="autodetectUserTransaction" value="true"/>
        </bean>
    
    </beans>
    and hibernate.cfg.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
      <session-factory name="SessionFactory">
        
        <property name="hibernate.current_session_context_class">org.hibernate.context.JTASessionContext</property>
        
        <property name="hibernate.connection.datasource">jdbc/mysql</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        
        <property name="hibernate.jndi.url">localhost:3700</property>
        <property name="hibernate.jndi.class">com.sun.enterprise.naming.SerialInitContextFactory</property>
        
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
        <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</property>
        <property name="jta.UserTransaction">java:comp/UserTransaction</property>
        <property name="hibernate.transaction.flush_before_completion">true</property>
        <property name="hibernate.transaction.auto_close_session">true</property>
        
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>
        <property name="use_sql_comments">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        
        <mapping class="pl.TestEntity"/>
      </session-factory>
    </hibernate-configuration>
    And logs...
    Code:
    2009-09-28 19:03:14,594 [httpSSLWorkerThread-8080-1] DEBUG (SpringBeanFacesELResolver.java:91)  Successfully resolved variable 'manager' in Spring ApplicationContext
    2009-09-28 19:03:14,596 [httpSSLWorkerThread-8080-1] DEBUG (AbstractBeanFactory.java:203)  Returning cached instance of singleton bean 'myRepository'
    2009-09-28 19:03:14,601 [httpSSLWorkerThread-8080-1] DEBUG (AbstractPlatformTransactionManager.java:319)  Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@1fdb0e5]
    2009-09-28 19:03:14,604 [httpSSLWorkerThread-8080-1] DEBUG (AbstractPlatformTransactionManager.java:347)  Creating new transaction with name [pl.Manager.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Throwable
    2009-09-28 19:03:14,605 [httpSSLWorkerThread-8080-1] DEBUG (TransactionSynchronizationManager.java:222)  Initializing transaction synchronization
    2009-09-28 19:03:14,644 [httpSSLWorkerThread-8080-1] DEBUG (JDBCContext.java:172)  successfully registered Synchronization
    2009-09-28 19:03:14,644 [httpSSLWorkerThread-8080-1] DEBUG (SessionImpl.java:220)  opened session at timestamp: 12541573946
    before save
    2009-09-28 19:03:14,660 [httpSSLWorkerThread-8080-1] DEBUG (AbstractSaveEventListener.java:297)  executing identity-insert immediately
    2009-09-28 19:03:14,662 [httpSSLWorkerThread-8080-1] DEBUG (AbstractBatcher.java:366)  about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    2009-09-28 19:03:14,662 [httpSSLWorkerThread-8080-1] DEBUG (ConnectionManager.java:421)  opening JDBC connection
    2009-09-28 19:03:14,665 [httpSSLWorkerThread-8080-1] DEBUG (AbstractBatcher.java:401)  
        /* insert pl.TestEntity
            */ insert 
            into
                TestEntity
                (text) 
            values
                (?)
    Hibernate: 
        /* insert pl.TestEntity
            */ insert 
            into
                TestEntity
                (text) 
            values
                (?)
    2009-09-28 19:03:14,772 [httpSSLWorkerThread-8080-1] DEBUG (IdentifierGeneratorFactory.java:37)  Natively generated identity: 1
    2009-09-28 19:03:14,776 [httpSSLWorkerThread-8080-1] DEBUG (AbstractBatcher.java:374)  about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    2009-09-28 19:03:14,776 [httpSSLWorkerThread-8080-1] DEBUG (ConnectionManager.java:404)  aggressively releasing JDBC connection
    2009-09-28 19:03:14,777 [httpSSLWorkerThread-8080-1] DEBUG (ConnectionManager.java:441)  releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    2009-09-28 19:03:14,780 [httpSSLWorkerThread-8080-1] DEBUG (AbstractPlatformTransactionManager.java:846)  Triggering beforeCompletion synchronization
    2009-09-28 19:03:14,782 [httpSSLWorkerThread-8080-1] DEBUG (AbstractPlatformTransactionManager.java:751)  Initiating transaction rollback
    2009-09-28 19:03:14,784 [httpSSLWorkerThread-8080-1] DEBUG (AbstractPlatformTransactionManager.java:875)  Triggering afterCompletion synchronization
    2009-09-28 19:03:14,785 [httpSSLWorkerThread-8080-1] DEBUG (TransactionSynchronizationManager.java:276)  Clearing transaction synchronization

  • #2
    First off all I suggest you configure hibernate in 1 location instead of 2 locations. Secondly I suggest you tell hibernate to use the configured transactionmanager from the application context instead of wiring its own.

    Rewrite your application context to something like this.

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
    
        <context:component-scan base-package="pl"/>
    
        <jee:jndi-lookup id="dataSource" jndi-name="jdbc/greatEnglish" />
    
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jtaTransactionManager" ref="platformTransactionManager" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.hbm2ddl.auto">create</prop>
    		<prop key="hibernate.show_sql">true</prop>
    		<prop key="hibernate.format_sql">true</prop>
    		<prop key="hibernate.use_sql_comments">true</prop>
    		<!-- Not sure if these 2 are needed -->
    		<prop key="hibernate.jndi.url">localhost:3700</prop>
    		<prop key="hibernate.jndi.class">com.sun.enterprise.naming.SerialInitContextFactory</prop>
    		<!-- If it doesn't work uncomment this line -->
    		<!--
    		<prop name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</prop>
    		-->
                </props>
            </property>
    	<property name="annotatedClasses">
    		<value>pl.TestEntity</value>
    	</property>
        </bean>
    
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <jee:jndi-lookup id="platformTransactionManager" jndi-name="java:appserver/TransactionManager" resource-ref="false" expected-type="javax.transaction.TransactionManager"/>
    
        <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    	<property name="transactionManager" ref="platformTransactionManager" />
            <property name="autodetectUserTransaction" value="true"/>
        </bean>
    
    </beans>
    Spring configures hibernate for you, you are overriding some of the properties and values needed for correct operation. Next to that there are some differences between the applicationcontext and hibernate.cfg.xml
    1) Why do you use 2 different datasources?
    2) You are messing around with transaction attributes, spring manages these for y ou
    3) Factory class is set by spring same for lookup class
    Last edited by Marten Deinum; Sep 28th, 2009, 02:36 PM. Reason: Fixed typo and layout

    Comment


    • #3
      Thank you very much now is working exacltly how its supposed to be

      Comment

      Working...
      X