Doc: Inheritance of @Transactional and lookup behaviour of AbstractFallbackTransactionAttributeSource [SPR-12474] #17080
Description
Ravi Sanwal opened SPR-12474 and commented
Lets start with a question to the expert.
Consider a service(or repo) bean
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* A service class with transactional method
*/
@Service
public class ServiceBean implements ServiceInterface {
@Transactional
public void serviceMethodA() {}
public void serviceMethodB() {}
}
And a subclass of it
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Extended {@link ServiceBean}
*/
@Service
@Transactional
public class MagicalServiceBean extends ServiceBean {
}
Notice that only one method of ServiceBean is marked @Transactional
while MagicalServiceBean has a class level @Transactional
declaration.
What should be the transactional nature of method serviceMethodB when it is called on an injected (and proxied et al.) instance of MagicalServiceBean?
Apparently as per the apidocs of org.springframework.transaction.interceptor.AnnotationTransactionAttributeSource (org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource) we expect to get a transactional serviceMethodB.
Abstract implementation of TransactionAttributeSource that caches attributes for methods and implements a fallback policy: 1. specific target method; 2.target class; 3. declaring method; 4. declaring class/interface.
A specific distinction is mentioned between target class and declaring class/interface
Codewise if we look at org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method, Class<?>), the targetClass parameter points to MagicalServiceBean.class.
You may consider it as a documentation defect.
There could be arguments for both "should apply transactional on extended method"(because this seems more intuitive and correct) and "should not apply on extended method"(to keep it the way base class has defined and because we can always create a delegate method on the extended class if we need to make it transactional)
Regardless this seems to be an odd behavior to me.
Affects: 4.1.2