An @Async
method in a @Service
-annotated class is not being called asynchronously - it\'s blocking the thread.
I\'ve got
Jiří Vypědřík's answer solved my problem. Specifically,
- Check if your method annotated with @Async is public.
Another useful information from Spring tutorials https://spring.io/guides/gs/async-method/:
Creating a local instance of the FacebookLookupService class does NOT allow the findPage method to run asynchronously. It must be created inside a @Configuration class or picked up by @ComponentScan.
What this means is that if you had a static method Foo.bar(), calling it in that manner wouldn't execute it in async, even if it was annotated with @Async. You'll have to annotate Foo with @Component, and in the calling class get an @Autowired instance of Foo.
Ie, if you have a annotated method bar in class Foo:
@Component
class Foo {
@Async
public static void bar(){ /* ... */ }
@Async
public void bar2(){ /* ... */ }
}
An in your caller class:
class Test {
@Autowired Foo foo;
public test(){
Foo.bar(); // Not async
foo.bar(); // Not async
foo.bar2(); // Async
}
}
Edit: Seems like calling it statically also doesn't execute it in async.
Hope this helps.
Firstly make your .xml
config looks like:
<task:scheduler id="myScheduler" pool-size="10" />
<task:executor id="myExecutor" pool-size="10" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler" proxy-target-class="true" />
(Yes, scheduler count and executor thread pool size is configurable)
Or just use default:
<!-- enable task annotation to support @Async, @Scheduled, ... -->
<task:annotation-driven />
Secondly make sure @Async
methods are public.
For me the solution was to add @EnableAsync
on my @Configuration
annotated class:
@Configuration
@ComponentScan("bla.package")
@EnableAsync
public class BlaConfiguration {
}
Now the class in package bla.package
which has @Async
annotated methods can really have them called asynchronously.
write a independent Spring configuration for asynchronous bean.
for example:
@Configuration
@ComponentScan(basePackages="xxxxxxxxxxxxxxxxxxxxx")
@EnableAsync
public class AsyncConfig {
/**
* used by asynchronous event listener.
* @return
*/
@Bean(name = "asynchronousListenerExecutor")
public Executor createAsynchronousListenerExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100);
executor.initialize();
return executor;
}
}
I overcome this problem with this situation.
You need 3 lines of code for Async to work
@Service @EnableAsync public myClass {
@Async public void myMethod(){
}