13

I am using Spring @Async on two classes. Both are ultimately implementing an interface. I am creating two separate ThreadPoolTaskExecutor so each class has its own ThreadPool to work off of. However due to I think something with proxy and how Spring implements Async classes, I have to put the @Async annotation on the base interface. Because of this, both classes end up using the same ThreadPoolTaskExecutor. Is it possible to tell Spring that for this Bean (in this case I am calling the classes that implement that interface a Service), use this ThreadPoolTaskExecutor.

Kirit
  • 389
  • 2
  • 3
  • 11

1 Answers1

23

By default when specifying @Async on a method, the executor that will be used is the one supplied to the 'annotation-driven' element as described here.

However, the value attribute of the @Async annotation can be used when needing to indicate that an executor other than the default should be used when executing a given method.

@Async("otherExecutor")
void doSomething(String s) {
    // this will be executed asynchronously by "otherExecutor"
}

In this case, "otherExecutor" may be the name of any Executor bean in the Spring container, or may be the name of a qualifier associated with any Executor, e.g. as specified with the element or Spring’s @Qualifier annotation

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

And probably you need to specify the otherExecutor bean in you app with the pool settings you wish.

@Bean
public TaskExecutor otherExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(5);
    executor.setMaxPoolSize(10);
    executor.setQueueCapacity(25);

    return executor;
}
Abdullah Khan
  • 12,010
  • 6
  • 65
  • 78
Imran
  • 1,732
  • 3
  • 21
  • 46
  • Even with the qualifier though, how would the implemented classes know which TaskExecutor to use. By specifying only a single 'name' or 'qualifier' at the interface level for the TaskExecutor, when both classes methods are invoked, it will call the same TaskExecutor. Ideally what I want to do is define Async at the implemented classes but it isn't working as expected in this case – Kirit Aug 19 '17 at 22:13
  • No, what is the reason preventing you from putting the annotation at implementation class? Of course you can do that with extra coding, but I don't see any reason for that. What does that mean "However due to I think something with proxy and how Spring implements Async classes, I have to put the @Async annotation on the base interface."? – Imran Aug 19 '17 at 22:22
  • My mistake @Imran, I can put it at the implementaiton class but I noticed it was calling the ThreadPool I wanted it too. I figured out why though. I had an abstract class in the middle that I implemented a few of the methods. Unless the final implemented class overrode those methods even if just calling super.method(), it would use the default Pool instead of the one specified. Thanks – Kirit Aug 19 '17 at 22:33