Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Async Not Working

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?

like image 482
EngineerBetter_DJ Avatar asked Jul 07 '11 12:07

EngineerBetter_DJ


People also ask

How does @async work in Spring?

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.

What is the use of @async in Spring boot?

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.

Does @async work on private method?

Never use @Async on top of a private method. In runtime, it will not able to create a proxy and, therefore, not work.


1 Answers

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.

like image 113
Shivan Dragon Avatar answered Sep 19 '22 06:09

Shivan Dragon