Reputation: 3595
I have an abstract base service, and two implementations:
public abstract class AbstractBaseService {
public void mainProcess() {
for (Foo foo : getFoos()) {
doSomething(foo);
}
}
abstract List<Foo> getFoos();
abstract void doSomething(Foo foo);
}
public class ServiceImplOne extends AbstractBaseService {
protected List<Foo> getFoos() { ... }
protected void doSomething(Foo foo) { ... }
}
public class ServiceImplTwo extends AbstractBaseService { ... }
If something goes wrong in doSomething(foo)
, I want to rollback any changes made with that object, write the error in a log file, and continue with the next object in the list. So, I'll add a try-catch inside the loop in my base service... and annotate with @Transactional
the doSomething
method in the implementation classes. But according to the Spring's docs:
When you use proxies, you should apply the
@Transactional
annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the@Transactional
annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. If you need to annotate non-public methods, consider using AspectJ (described later).
My methods are protected
... I could change the visibility to public
, but there is also the issue that:
The default advice mode for processing
@Transactional
annotations isproxy
, which allows for interception of calls through the proxy only. Local calls within the same class cannot get intercepted that way. For a more advanced mode of interception, consider switching toaspectj
mode in combination with compile-time or load-time weaving.
So, the proxy won't be able to intercept calls from within the same class. Does that also apply to calls between an abstract class and its implementations, or will it work as I intend? Is there any easy way to check it myself? (Probably a dumb question, I get a little lost when it comes to Java proxies...)
I've been searching for a while, but I've only managed to find these two questions, and they focus on inheritance of the @Transactional
tag itself... which is not really important in this case, I don't care annotating all the doSomething
implementations instead of just the abstract method.
Upvotes: 2
Views: 1404
Reputation: 691685
An instance of ServiceImplOne
is an instance of AbstractBaseService
. There is a single object being created when you create an instance of ServiceImplOne
. And its mainProcess()
method calls its doSomething()
method.
The call isn't a call from one Spring bean to another Spring bean, so there's nothing that can be intercepted.
Upvotes: 2