Skip to content

Doc: Inheritance of @Transactional and lookup behaviour of AbstractFallbackTransactionAttributeSource [SPR-12474] #17080

Closed
@spring-projects-issues

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

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)in: dataIssues in data modules (jdbc, orm, oxm, tx)status: bulk-closedAn outdated, unresolved issue that's closed in bulk as part of a cleaning process

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions