A method annotated with Spring’s @Async or @Transactional annotations will not work as expected if invoked directly from
within its class.
This is because Spring generates a proxy class with wrapper code to manage the method’s asynchronicity (@Async) or to handle the
transaction (@Transactional). However, when called using this, the proxy instance is bypassed, and the method is invoked
directly without the required wrapper code.
Replace calls to @Async or @Transactional methods via this with calls on an instance that was injected by
Spring (@Autowired, @Resource or @Inject). The injected instance is a proxy on which the methods can be invoked
safely.
@Service
public class AsyncNotificationProcessor implements NotificationProcessor {
@Override
public void process(Notification notification) {
processAsync(notification); // Noncompliant, call bypasses proxy
}
@Async
public processAsync(Notification notification) {
// ...
}
}
@Service
public class AsyncNotificationProcessor implements NotificationProcessor {
@Resource
private AsyncNotificationProcessor
@Override
public void process(Notification notification) {
asyncNotificationProcessor.processAsync(notification); // Compliant, call via injected proxy
}
@Async
public processAsync(Notification notification) {
// ...
}
}