Categories
java spring

Spring @Async ignored

I am having troubles invoking a method asynchronously in Spring, when the invoker is an embedded library receiving notifications from an external system. The code looks as below:

@Service
public class DefaultNotificationProcessor implements NotificationProcessor {
private NotificationClient client;
@Override
public void process(Notification notification) {
processAsync(notification);
}
@PostConstruct
public void startClient() {
client = new NotificationClient(this, clientPort);
client.start();
}
@PreDestroy
public void stopClient() {
client.stop();
}
@Async
private void processAsync(Notification notification) {
// Heavy processing
}
}

The NotificationClient internally has a thread in which it receives notifications from another system. It accepts a NotificationProcessor in its constructor which is basically the object that will do the actual processing of notifications.

In the above code, I have given the Spring bean as the processor and attempted to process the notification asynchronously by using @Async annotation. However, it appears the notification is processed in the same thread as the one used by NotificationClient. Effectively, @Async is ignored.

What am I missing here?

@Async (as well as @Transactional and other similar annotations) will not work when the method is invoked via this (on when @Async is used for private methods*), as long as you do not use real AspectJ compiletime or runtime weaving.

*the private method thing is: when the method is private, then it must been invoked via this – so this is more the consequence then the cause

So change your code:

@Service
public class DefaultNotificationProcessor implements NotificationProcessor {
@Resource
private DefaultNotificationProcessor selfReference;
@Override
public void process(Notification notification) {
selfReference.processAsync(notification);
}
//the method must not been private
//the method must been invoked via a bean reference
@Async
void processAsync(Notification notification) {
// Heavy processing
}
}

See also the answers for: Does Spring @Transactional attribute work on a private method? — this is the same problem