'@Transactional not rolling back transaction in Spring

I am using Spring Jdbc and @Transactional annotation for a method which inserts data in the database. Snippet of code is:

@Transactional(rollbackForClassName={"Exception"})
    public PreBookingResponse saveData(Tip trip, HttpServletRequest request) throws Exception {
        PreBookingResponse preBookingResponse = null;
        try {
            String bookingRefNo = "89";
            trip.setBookingRefNo(bookingRefNo);
            MinimumUserProfile userProfile = JwtService.getUserFromToken(request);
            String userId = userProfile.getUserId();
            
            if (tripDao.saveTripData(trip, userId)) {
                preBookingResponse = new PreBookingResponse(0, "");
                preBookingResponse.setBookingRefNo(bookingRefNo);
                preBookingResponse.setSearchId(trip.getSearchId());
                preBookingResponse.setId(trip.getId());
            }
        }catch(Exception e)
        {
            String errorMsg = "Error occur while saving trip data due to: " + e.getMessage();
            log.error(errorMsg);
            preBookingResponse = new PreBookingResponse(2, errorMsg);
            preBookingResponse.setBookingRefNo(trip.getBookingRefNo());
            preBookingResponse.setSearchId(trip.getSearchId());
            throw e;
        }
        return preBookingResponse;
    }

Inside function tripDao.saveTripData(trip, userId) I am insrting data in more than one table. When any exception occurs while inserting data all the insertion operations should roll back but they don't.

My spring-config.xml is (which I am importing from another project):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
    
    
    <!-- Enable Annotation based Declarative Transaction Management -->
    <tx:annotation-driven proxy-target-class="true"
        transaction-manager="transactionManager" />
        
    

    <!-- Creating TransactionManager Bean, since JDBC we are creating of type 
        DataSourceTransactionManager -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
    <!-- MySQL database connection -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306/aapi"></property>
        <!-- Changed to mysql-connector-java 5.x since 6 is in beta phase  -->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
</beans>

My build.gradle is:

buildscript {
    ext {
        springBootVersion = '1.5.2.RELEASE'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}


apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    jcenter()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.2.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: '1.5.2.RELEASE'

    compile project(':supplier-commons')
    runtime project(':supplier-commons')

    compile 'org.springframework:spring-context:4.2.6.RELEASE'
    compile 'org.springframework:spring-webmvc:4.2.6.RELEASE'
    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.6'
    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.7'
    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.7'
    compile group: 'com.typesafe.akka', name: 'akka-actor_2.11', version: '2.4.1'
    compile 'io.jsonwebtoken:jjwt:0.7.0'
    compile group: 'javax.mail', name: 'mail', version: '1.4'
    compile group: 'freemarker', name: 'freemarker', version: '2.3.9'
    compile group: 'org.springframework.security', name: 'spring-security-crypto', version: '4.2.2.RELEASE'
    compile group: 'org.apache.commons', name: 'commons-email', version: '1.4'
    compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.4.9'
    compile group: 'org.jmockit', name: 'jmockit', version: '1.8'
    compile 'io.jsonwebtoken:jjwt:0.7.0'
    compile group: 'com.ning', name: 'async-http-client', version: '1.6.4'
    compile group: 'org.mockito', name: 'mockito-all', version: '1.8.4'
    compile group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.0.7'
 
    runtime('org.springframework.boot:spring-boot-devtools')
    compileOnly('org.springframework.boot:spring-boot-configuration-processor')
    compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.8.8'
    // https://mvnrepository.com/artifact/org.springframework/spring-tx
    compile group: 'org.springframework', name: 'spring-tx', version: '4.1.4.RELEASE'
    // https://mvnrepository.com/artifact/org.eclipse.persistence/javax.persistence
compile group: 'org.eclipse.persistence', name: 'javax.persistence', version: '2.1.0'
    // https://mvnrepository.com/artifact/org.hibernate/hibernate-core

    // https://mvnrepository.com/artifact/org.hibernate/hibernate-core
compile group: 'org.hibernate', name: 'hibernate-core', version: '3.6.5.Final'
    // https://mvnrepository.com/artifact/org.springframework/spring-orm
compile group: 'org.springframework', name: 'spring-orm', version: '4.3.8.RELEASE'
    // https://mvnrepository.com/artifact/org.hibernate/hibernate
compile group: 'org.hibernate', name: 'hibernate', version: '3.2.6.ga'
    
    testCompile 'junit:junit:4.12'
   
}

springBoot {
    executable = true
}

eclipse {

  wtp {
    facet {
        facet name: 'jst.web', version: '2.4'
    }
  
    component {
      contextPath = 'aggregator-api'
    }
    
  }
}

Why are the transactions not rolling back?



Solution 1:[1]

This code does not rollback the transaction becoz the exception is not thrown back to the method.

@Transactional(rollbackForClassName={"Exception"}) means rollback the transaction when Exception is thrown back from this method. But in your case you are catching the exception and returning a proper response hence the transaction is getting commited. Spring creates a AOP transaction advice around this method call which successfully commits if method gracefully returns, and rollbacks if exception thrown from this method.

To rollback either throw the exception from this method or move the code inside try block to a different method and annotate that method with @Transactional(rollbackForClassName={"Exception"})

Solution 2:[2]

You need to disable defaultAutoCommit in dataSource.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Praneeth Ramesh
Solution 2 Vinit Solanki