Asynchronous method invocation in Spring 3.0
Spring 3.0 has added annotation support for both task scheduling and asynchronous method execution. We will discuss @Async annotation and its uses.
The @Async annotation
The @Async annotation allows invocation of that method to occur asynchronously. In other words, the caller will return immediately upon invocation.
One of the use cases of @Async function can be in situations where in user registers and system has to send confirmation mail or any similar task where you do not want to block user.
We will look at the example below to explain it more clearly . Since for most of you this will be first Spring 3.0 application, please notice the changes in applicationContext.xml.
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:p=”http://www.springframework.org/schema/p” xmlns:context=”http://www.springframework.org/schema/context”
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”><context:component-scan base-package=”cs”/>
</beans>
Let us now look at our classes
TestService.java
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cs.service.RegularService;public class TestService {
public static void main(String args[]){
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[] {
“applicationContext.xml”});RegularService regService = (RegularService) appContext.getBean(“regularService”);
regService.registerUser(“Skill-Guru”);
}
}
RegularService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import cs.async.MailUtility;
@Service
public class RegularService {@Autowired
private MailUtility mailUtility ;public void registerUser(String userName){
System.out.println(” User registration for “+userName +” complete”);
mailUtility.sendMail(userName);
System.out.println(” Registration Complete. Mail will be send after 5 seconds “);
}}
MailUtility.java
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;@Component
public class MailUtility {@Async
public void sendMail(String name){System.out.println(” I Will be formatting html mail and sending it “);
try {
Thread.sleep(10000);} catch (InterruptedException e) {
e.printStackTrace();
}System.out.println(” Asynchronous method call of send email — Complete “);
}
}
Once you run the TestService.java the output would be
User registration for Skill-Guru complete
I Will be formatting html mail and sending it
Asynchronous method call of send email — Complete
Registration Complete. Mail will be send after 5 seconds
Now wait a minute. This does not look like asynchronous call. What the hell is wrong here ?
We missed <task:annotation-driven/> in applicationContext.xml
The modified applicationContext.xml would be
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:p=”http://www.springframework.org/schema/p” xmlns:context=”http://www.springframework.org/schema/context”
xmlns:task=”http://www.springframework.org/schema/task”
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“><context:component-scan base-package=”cs”/>
<task:annotation-driven/>
</beans>
Notice the changes in bold.
Now run your TestService again. The output would be
User registration for Skill-Guru complete
Registration Complete. Mail will be send after 5 seconds
I Will be formatting html mail and sending it
The program will not exit and after 5 second you will see
Asynchronous method call of send email — Complete
You can see registerUser calls sendMail and the control is returned back to caller immediately.


oh, i like new info about Asynchronous. Thanks guys!
Thank you for your introduction. It’s really helpful.
Thanks mKyong for mentioning the post. I appreciate it.
Hello, I have tried the example above and unfortunately it does not works
When I run the TestService it prints only:
User registration for Skill-Guru complete
Registration Complete. Mail will be send after 5 seconds
But MailUtility.sendMail method is not invoked.
When I removed the @Async annotation I got all four messages:
User registration for Skill-Guru complete
I Will be formatting html mail and sending it
Asynchronous method call of send email — Complete
Registration Complete. Mail will be send after 5 seconds
Any idea whats wrong? Why the sendMail method is not invoked?
Many thanks for any help!
Sorry, the problem was caused by implementing an TestService as junit test in my case and the junit test finished before background threads write anything to stdout.
Many thanks for great example!