Search code examples
javaspringspring-transactionsrollback

Transaction rollback not working with Propagation.REQUIRES_NEW when default rollback rule is set


I use MyBatis 3.4.5 and Spring 4.1.6. I have checked abstract class GenericException (extends Exception) and CustomException (extends GenericException). I set default rollback for GenericException in tx:

<tx:advice id="txSetRollBackForCoreExceptionsAdvice" transaction-manager="transactionManager">
  <tx:attributes>
      <tx:method name="*" rollback-for="RuntimeException,xxx.exceptions.GenericException"/>
  </tx:attributes>
</tx:advice>

Method in Service1:

 @Override
public Long push(TimerState timerState) {
    try {
        return timerStatePushService.pushEvent(timerState);
    }catch (Exception e) {
        throw  new TimerException(e.getMessage());
    }
}

Service2:

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Service
public class TimerStatePushServiceBean implements TimerStatePushService {
@Autowired
PushService pushService;

@Override
public Long pushEvent(TimerState timerState) throws GenericException {
        return pushService.pushEventById(timerState.getId());
}

If pushService throws CustomException (which extends GenericException), i catch UnexpectedRollbackException in Service1. And in trace log i see:

12:42:48.677 TRACE {pool-15-thread-1} [o.s.t.i.RuleBasedTransactionAttribute] : Applying rules to determine whether transaction should rollback on xxx.exceptions.CustomException
12:42:48.677 TRACE {pool-15-thread-1} [o.s.t.i.RuleBasedTransactionAttribute] : Winning rollback rule is: null
12:42:48.677 TRACE {pool-15-thread-1} [o.s.t.i.RuleBasedTransactionAttribute] : No relevant rollback rule found: applying default rules
12:42:48.677 DEBUG {pool-15-thread-1} [o.s.j.d.DataSourceTransactionManager] : Global transaction is marked as rollback-only but transactional code requested commit

If i set "rollbackFor = GenericException.class" - it's all ok:

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = GenericException.class)
@Service
public class TimerStatePushServiceBean implements TimerStatePushService {
@Autowired
PushService pushService;

@Override
public Long pushEvent(TimerState timerState) throws GenericException {
        return pushService.pushEventById(timerState.getId());
}

If i throw CustomException in mehtod "pushEvent" without set rollbackFor - it's all ok:

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Service
public class TimerStatePushServiceBean implements TimerStatePushService {
@Autowired
PushService pushService;

@Override
public Long pushEvent(TimerState timerState) throws GenericException {
        throw new CustomException("msg");
}

I don't understand what's going on. For information: I need rollback transaction in TimerStatePushService and don't rollback transaction in Service1.


Solution

  • I've resolved problem. I have two modules: core and manager. For core is set:

    <aop:config>
        <aop:pointcut expression="within(xxx.core..*) &amp;&amp; @within(org.springframework.stereotype.Service)"
                      id="inCoreServiceCall"/>
        <aop:advisor order="1"
                     advice-ref="txSetRollBackForCoreExceptionsAdvice"
                     pointcut-ref="inCoreServiceCall"/>
    </aop:config>
    

    PushService in core module, another services in manager module. I added setting for manager module.