AJPerez
AJPerez

Reputation: 3595

Using Spring transaction proxy between abstract class and child method

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 is proxy, 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 to aspectj 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

Answers (1)

JB Nizet
JB Nizet

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

Related Questions