Why is this an issue?

Marking a non-public method @Async or @Transactional is misleading because, up to version 5, Spring does not recognize non-public methods, and so makes no provision for their proper invocation. Nor does Spring make provision for the methods invoked by the method it called. Since Spring 6, protected and package-private methods can be handled, but the issue remains for private methods.

Therefore, marking a private method, for instance, @Transactional gives a false sense of security, and can lead to incorrect assumptions and potential bugs.

Exceptions

The rule targets all non-public methods for project using Spring up to Spring 5, but only private methods for Spring 6 because Spring 6 takes into account all non-private methods.

How to fix it

Declare the method public. Note that this action alone does not resolve the issue of direct instance calls from within the same class (see rule {rule:java:S6809}), but it is a required precondition to fix it.

Code examples

Noncompliant code example

@Async
private Future<String> asyncMethodWithReturnType() { // Noncompliant, no proxy generated and
    return "Hellow, world!";                         // can only be invoked from same class
}

Compliant solution

@Async
public Future<String> asyncMethodWithReturnType() { // Compliant
    return "Hellow, world!";
}

Resources

Documentation

Articles & blog posts