Spring @Async Not Working
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.
With the help of this excellent answer by Ryan Stewart, I was able to figure this out (at least for my specific problem).
In short, the context loaded by the ContextLoaderListener
(generally from applicationContext.xml) is the parent of the context loaded by the DispatcherServlet
(generally from *-servlet.xml
). If you have the bean with the @Async
method declared/component-scanned in both contexts, the version from the child context (DispatcherServlet
) will override the one in the parent context (ContextLoaderListener
). I verified this by excluding that component from component scanning in the *-servlet.xml
-- it now works as expected.
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.
- Try adding
proxy-target-class="true"
to all<*:annotation-driven/>
elements that support this attribute. - Check if your method annotated with
@Async
is public.