2

I have a code like below

   public abstract class AffltTransactionService implements IAffltTransactionService {
    ....

        @Override
        @Transactional
        public void processTransactions(List<? extends AffltTransaction> transactions) {
            for (AffltTransaction transaction : transactions) {
                if (transaction != null) {
                    processTransaction(transaction);
                }
            }
        }

        private void processTransaction(AffltTransaction transaction) {
            try {
                processTransactionInternal(transaction);

            } catch (Exception exception) {
                affltTransactionError = new AffltTransactionError(null, null, "error", new Date());
                saveAffltTransactionError(affltTransactionError);
                log.error(exception.getLocalizedMessage());
            }
        }

        @Transactional(readOnly=false, rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
        public void processTransactionInternal(AffltTransaction transaction) {

processTransactionInternal throws ServiceUnAvailableException which extends RuntimeException

But the transaction is not getting rolled back despite having rollbackFor = Exception.class . Can you please help.

Sammy Pawar
  • 1,201
  • 3
  • 19
  • 38
  • 2
    see this answer: http://stackoverflow.com/a/4396530/280244 - it explain when the annotation is taken in account. In your case it is not taken in account, therefore there is no roleback. – Ralph Apr 09 '14 at 09:14

5 Answers5

11

@Transactional annotation won't have any effect if you are calling the method directly, since Spring creates proxies above annotated classes and the aspect-defined functionality is implemented by proxy. So, when you call the method from within your class it doesn't get through proxy, and hence no transcation is created and/or rolled back.

Take a look at the Spring reference for detailed explanation.

Vladimir
  • 9,683
  • 6
  • 36
  • 57
2

Since you invoke one method from another within the same bean, the Spring AOP doesn't use any advices in this case.

Only processTransactions is wrapped with TransactionInteceptor.

To make it worked you should configure:

<aop:aspectj-autoproxy expose-proxy="true"/>

But it isn't recommened, though.

More info here: http://www.intertech.com/Blog/secrets-of-the-spring-aop-proxy

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
1

Use getCurrentSession instead of opensession

1

I know it was asked a long time ago but I faced with the same issue and for me was missing Spring configurantion annotation:

@EnableTransactionManagement

After write it on ApplicationConfiguration class it was solved. I hope it helps someone on future.

Karpinski
  • 118
  • 4
  • 10
0

The method you use apply @Transactional should throws exception. Don't use try-catch instead.(I guess you use try-catch in somewhere in your processTransaction function). Code should be like this:

@Transactional
    public void processTransactions(List<? extends AffltTransaction> transactions) threws Exception{
        for (AffltTransaction transaction : transactions) {
            if (transaction != null) {
                processTransaction(transaction);
            }
        }
    }