How to rollback Spring Transaction when an Exception is thrown

36,875

Solution 1

Your transaction is not rollbacked because there is no exception thrown: the addState() method that you call catches the exception:

public void addState() {
    try {
        State state=new State();
        state.setStateName("Delhi");
        stateDao.create(state);
        addCity();
        addCustomer();
    }
    catch(Exception e) {
        e.printStackTrace();
    }
}

So the transactional Spring proxy doesn't see any exception thrown and doesn't rollback the transaction.

It works for exceptions thrown from the DAO because the DAO is itself transactional, so its own transactional proxy detects the exception being thrown by the DAO and marks the transaction for rollback. The exception is then propagated to the service and caught by your code, but the transaction is already marked for rollback at this point.

Solution 2

Your transaction is not getting rolled back because you are not letting Exception to reach to Spring framework, you are catching the exception in your code itself. So instead of

public void addState() 
{
        try
        {
        State state=new State();
        state.setStateName("Delhi");
        stateDao.create(state);
        addCity();
        addCustomer();
        }
        catch(Exception e)
        {

            e.printStackTrace();
        }
}

use

public void addState() 
{
        State state=new State();
        state.setStateName("Delhi");
        stateDao.create(state);
        addCity();
        addCustomer();
}

Solution 3

The transaction has not been rolled back, because you are catching the exception yourself, by writing catch block..

This can be done in normal cases, but in spring transaction, if you do so, how does spring transaction manager knows the exception is happening.. thats why it is not getting rolled back.

Share:
36,875
arvin_codeHunk
Author by

arvin_codeHunk

J2ee/web developer

Updated on July 05, 2022

Comments

  • arvin_codeHunk
    arvin_codeHunk almost 2 years

    I am using spring 3.0.5 and hibernate 3.6. In my project there is a scenario where i have to rollback transaction of any exception in thrown or error occurs. This the sample code, Everything works fine except transaction is not getting rolled back when I throw an Exception but if any exception is thrown such as mysql.IntegrityConstraintException then transaction gets rolled back, why this is not happening in my case?

    applicationContext.xml

        <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:database.properties"/>
        </bean>
          <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
                <property name="driverClassName" value="${jdbc.driverClassName}" />
                <property name="url" value="${jdbc.url}" />
                <property name="username" value="${jdbc.username}" />
                <property name="password" value="${jdbc.password}" />
    
            </bean>
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
     <property name="dataSource" ref="myDataSource" />
        <property name="packagesToScan" value="com.alw.imps"/>
        <property name="configLocation">    
            <value>
                classpath:hibernate.cfg.xml
            </value>
         </property>
        </bean>
    
        <bean id="stateDao" class="com.alw.imps.dao.StateDaoImpl">
         <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
    
    
            <bean id="stateService" class="com.alw.imps.services.StateService">
           <property name="stateDao" ref="stateDao"></property>
           <property name="cityDao" ref="cityDao"></property>
           <property name="customerDao" ref="customerDao"></property>
           </bean>  
    
            <bean id="customerDao" class="com.alw.imps.dao.CustomerDaoImpl">
            <property name="sessionFactory" ref="sessionFactory"></property>
           </bean> 
    
                <bean id="cityDao" class="com.alw.imps.dao.CityDaoImpl">
                  <property name="sessionFactory" ref="sessionFactory"></property>
                </bean>  
    
    
    
    
    
    <tx:annotation-driven transaction-manager="transactionManager"  />
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>        
    
    <tx:advice id = "txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="*" propagation="REQUIRED" />
    </tx:attributes>
    </tx:advice>
    

    Service class StateService

    @Transactional(rollbackFor={Exception.class})
    public class StateService {
    
      private StateDaoImpl stateDao;
      private CityDao cityDao;
      private CustomerDao customerDao;
    
      public void setCustomerDao(CustomerDao customerDao) {
        this.customerDao = customerDao;
      }
    
      public void setStateDao(StateDaoImpl stateDao) {
        this.stateDao = stateDao;
      }
    
      public CityDao getCityDao() {
        return cityDao;
      }
    
      public void setCityDao(CityDao cityDao) {
        this.cityDao = cityDao;
      }
    
      public void addState() {
        try {
          State state=new State();
          state.setStateName("Delhi");
          stateDao.create(state);
          addCity();
          addCustomer();
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
    
      public void addCity() throws Exception {
        City city=new City();
        city.setCiytName("Delhi");
        city.setStateId(1);
        cityDao.create(city);
      }
    
      public void addCustomer() throws Exception {
        throw new java.lang.Exception();
      }
    

    DAO

    public class StateDaoImpl extends GenericDaoImpl<State, Integer> implements StateDao {
    }
    

    GenericDaoImpl

    public class GenericDaoImpl<T,PK extends Serializable> implements GenericDao<T,PK> {
      public SessionFactory sessionFactory;
      public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
      }
    
      public Session getSession() {
        return sessionFactory.getCurrentSession();
      }
    
      public PK create(T o) {
        Session ss= getSession();
        ss.save(o);
        return null;
      }
    

    hibernate.cfg

    <hibernate-configuration>
      <session-factory>
        <property name="connection.pool_size">1</property>
        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        <property name="defaultAutoCommit">false</property>
        <mapping class="com.alw.imps.pojo.State"/>
        <mapping class="com.alw.imps.pojo.City"/> 
      </session-factory>
    </hibernate-configuration>
    

    So as I said my problem is transaction is not getting rollback when i throw an exception of type Exception from method addCustomer()