topher-j
topher-j

Reputation: 2281

Spring Transactions not rolling back on Exception (Oracle JNDI datasource)

I am using annotation based transactions in a Spring MVC 3.1 project, and my transactions are not being rolled back when an exception is thrown.

Here is my Service code


@Service
public class ImportService {

    @Autowired
    ImportMapper importMapper;

    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, rollbackFor=Throwable.class)
    public void processImport() throws ServiceException, DatabaseException {
        iImport import = new Import();

        createImport(import);

        throw new ServiceException("");         
    }

    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, rollbackFor=Throwable.class)
    private void createImport(Import import) throws DatabaseException {
        try {
            importMapper.createImport(eventImport);
        } catch (Exception e) {
            throw new DatabaseException(e);
        }
    }

So, hopefully, the createImport method should be rolled back after the exception is thrown. But unfortunately it's not.

I am defining my datasource in the server context.xml

<Resource name="datasource.import" auth="Container" type="javax.sql.DataSource"
           maxActive="100" maxIdle="30" maxWait="10000"
           username="user" password="password" driverClassName="oracle.jdbc.driver.OracleDriver"
           url="jdbc:oracle:thin:@INFO" />

And I'm looking it up with JNDI:

<jee:jndi-lookup id="dataSource" jndi-name="datasource.import"/>

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

<tx:annotation-driven />

I'm using an Oracle database, and the JDBC spec says that auto commit is true by default. I thought that if I set it to false explicitly that would help, but I can't figure out how to do that.

Is there any way to get rollbacks working, while looking up your Oracle datasource by JNDI.

Upvotes: 5

Views: 1565

Answers (2)

Clement.Xu
Clement.Xu

Reputation: 1308

It is said that, if a @transational method is invoked by another @transational method, the first one will not work. You may try to remove the first @transational and have a try.

Upvotes: 0

Pavel Horal
Pavel Horal

Reputation: 18214

Please be aware that Spring's transaction management rolls-back transactions only for unchecked exceptions (RuntimeException) by default. If you wish to perform rollback also on checked exceptions, you need to define that.

When using annotations as attribute source, you need to provide rollbackFor attribute with the list of exception classes, which should cause a transaction to be rolled-back (quote from the JavaDoc):

/**
 * Defines zero (0) or more exception {@link Class classes}, which must be a
 * subclass of {@link Throwable}, indicating which exception types must cause
 * a transaction rollback.
 * <p>This is the preferred way to construct a rollback rule, matching the
 * exception class and subclasses.
 * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}
 */
Class<? extends Throwable>[] rollbackFor() default {};

Upvotes: 5

Related Questions