An @Async
method in a @Service
-annotated class is not being called asynchronously - it's blocking the thread.
I've got <task: annotation-driven />
in my config, and the call to the method is coming from outside of the class so the proxy should be being hit. When I step through the code, the proxy is indeed hit, but it doesn't seem to go anywhere near any classes related to running in a task executor.
I've put breakpoints in AsyncExecutionInterceptor
and they never get hit. I've debugged into AsyncAnnotationBeanPostProcessor
and can see advice getting applied.
The service is defined as an interface (with the method annotated @Async
there for good measure) with the implementation's method annotated @Async
too. Neither are marked @Transactional
.
Any ideas what may have gone wrong?
-=UPDATE=-
Curiously, it works only when I have my task
XML elements in my app-servlet.xml file, and not in my app-services.xml file, and if I do my component scanning over services from there too. Normally I have one XML file with only controllers in it (and restrict the component-scan accordingly), and another with services in it (again with a component-scan restricted such that it doesn't re-scan the controllers loaded in the other file).
app-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:webflow="http://www.springframework.org/schema/webflow-config" xmlns:task="http://www.springframework.org/schema/task" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd" > <task:annotation-driven executor="executor" /> <task:executor id="executor" pool-size="7"/> <!-- Enable controller annotations --> <context:component-scan base-package="com.package.store"> <!-- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> --> </context:component-scan> <tx:annotation-driven/> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <mvc:annotation-driven conversion-service="conversionService" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
app-services.xml (doesn't work when specified here)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <!-- Set up Spring to scan through various packages to find annotated classes --> <context:component-scan base-package="com.package.store"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <task:annotation-driven executor="han" /> <task:executor id="han" pool-size="6"/> ...
Am I missing something glaringly obvious in my configuration, or is there some subtle interplay between config elements going on?
Simply put, annotating a method of a bean with @Async will make it execute in a separate thread. In other words, the caller will not wait for the completion of the called method. One interesting aspect in Spring is that the event support in the framework also has support for async processing if necessary.
Here @EnableAsync is used for enabling asynchronous processing with Java Spring Boot Configuration and switches Spring's ability to run @Async methods. The @Async Methods run in the background thread pool without interruption other parallel processes.
Never use @Async on top of a private method. In runtime, it will not able to create a proxy and, therefore, not work.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With