Question

I am trying to incorporate Spring transactions into my project, and it seems that they are not working. I went through some tutorials nad Spring docs, and for me everything seems OK.

What I have: 1) context file:

<?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:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<bean id="jdbcTemplate" class="webapp.dataaccess.commons.JdbcTemplateProvider">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- dao section -->

<bean id="modesDao" class="webapp.dataaccess.opcalc.basicdao.CalcModesData">
    <property name="jdbc" ref="jdbcTemplate" />
</bean>

<!-- lots of DAO beans defined same way -->

2) data source defined on server:

<Resource name="jdbc/calc_webapp" auth="Container" type="javax.sql.DataSource"
           maxActive="100" maxIdle="30" maxWait="10000"
           username="user" password="password" driverClassName="org.postgresql.Driver"
           url="jdbc:postgresql://localhost:5432/service" defaultAutoCommit = "true" />

3) and finally in one of the DAO beans I have this method:

@Transactional(propagation=Propagation.REQUIRED)
public Boolean saveFullOrganization(OrganizationLevel org) throws Exception{
    Boolean out = true;
    try{
        Integer adminPermKey = permDao.saveAdminPermissions(org.getPermissions().getAdminPermission());
        org.getPermissions().setAdminPermissionKey(adminPermKey);
        Integer sellPermKey = permDao.saveSellingPermissions(org.getPermissions().getSellingPermission());
        org.getPermissions().setSellingPermissionKey(sellPermKey);
        Integer dszPermKey = permDao.saveDszPermissions(org.getPermissions().getDszPermission());
        org.getPermissions().setDszPermissionKey(dszPermKey);
        Integer reportPermKey = permDao.saveReportingPermissions(org.getPermissions().getReportingPermission());
        org.getPermissions().setReportingPermissionKey(reportPermKey);

        if(org.getPermissions().getKey()==null){
            Integer permissions = permDao.savePermissionsSet(org.getPermissions(), null);
            org.setPermissionsKey(permissions);
        }
        saveOrganizationUnit(org, org.getKey());
    }catch(Exception e){
        e.printStackTrace();
        throw e;
    }

    return out;
}

Flow is rather intuitive - first part of method prepares permission entries for organization unit (each operation in bean permDao is also transactional), then finally calls "saveOrganizationUnit" to finalize adding new entry. I assumed that with transaction management if any exception occure in the middle of that procedure, then no data from it will go to DB. But my tests proved that if I trigger artificial exception before "saveOrganizationUnit" operation (which interrupts whole process nad jumps out of the method) the permission part lands in DB anyway. So, as I understand, transactions are not working in my solution.

I am not sure what should I check and what can be wrong (I am kind of Spring noob, so please, don't kick if its something obvious).

Was it helpful?

Solution

Default behavour of @Transactional is defined as follows:

Any RuntimeException triggers rollback, and any checked Exception does not.

So, I guess you are throwing a checked exception. If you want to trigger rollback in this case, you need to configure @Transactional accordingly:

@Transactional(propagation=Propagation.REQUIRED, rollbackFor = Exception.class) ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top