Spring Annotation-Based vs XML-Based Transaction Definition Precedence
I couldn’t find a definitive answer to this in the docs, and although there seems to be a logical answer, one can’t be sure. The scenario is this – you have a xml-based transaction definition, like:
<tx:advice id="txAdvice" transaction-manager="jpaTransactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
Which advises all service methods. But then you have @Transactional
on a concrete class/method, where you want to override the propagation attribute.
It is clear that @Transactional
at method-level overrides the same one at class-level, but does it override the <tx:advice>
(and actually, the <aop:pointcut>
)?
It turns out the behaviour is less than expected:
- Both
<aop:advisor>
and @Transactional
(together with <tx:annotation-driven>
) create a TransactionInterceptor
around the target class (the one, whose methods are to be run in transaction).
- The advice with a lower
order
attribute overrides the other one. If no order attribute is specified, the order is undefined. But my tests showed that the one defined latest in the applicationContext.xml
takes precedence, although this might not be the case always:
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined.
This is the behaviour for spring 2.5.6. Spring 3.0 might have redefined this.
I couldn’t find a definitive answer to this in the docs, and although there seems to be a logical answer, one can’t be sure. The scenario is this – you have a xml-based transaction definition, like:
<tx:advice id="txAdvice" transaction-manager="jpaTransactionManager"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
Which advises all service methods. But then you have @Transactional
on a concrete class/method, where you want to override the propagation attribute.
It is clear that @Transactional
at method-level overrides the same one at class-level, but does it override the <tx:advice>
(and actually, the <aop:pointcut>
)?
It turns out the behaviour is less than expected:
- Both
<aop:advisor>
and@Transactional
(together with<tx:annotation-driven>
) create aTransactionInterceptor
around the target class (the one, whose methods are to be run in transaction). - The advice with a lower
order
attribute overrides the other one. If no order attribute is specified, the order is undefined. But my tests showed that the one defined latest in theapplicationContext.xml
takes precedence, although this might not be the case always:
When two pieces of advice defined in different aspects both need to run at the same join point, unless you specify otherwise the order of execution is undefined.
This is the behaviour for spring 2.5.6. Spring 3.0 might have redefined this.
I’m not sure about that. In my tests even though tx:annotation-driven has order lower than tx:advice in some cases tx:advice takes precedence instead of the other one (depending on the type of propagation).
I’d like to use both strategies but with @Transaction at method-level taking precedence. Do you know how to do this?
I was thinking to use something like this into pointcut of the tx:advice “all_services_public_methods() and not @annotation(org.springframework.transaction.annotation.Transactional)”.