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(5000);} 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.
Are you preparing for Spring Certification ? Try out the Spring certification Mock Practice test



i did the example exactly as described but the call does not seem to be Async it waits untill the sendMail finishes. i tried with wait(15000) it waits 15 seconds then it goes back to continue.
it seems that @Async does not work
please help
Hi,Is the Thread.sleep(5000) required for it to function asynchronously.?
Simple and excellent. Thank you!
async call stop processing(method which was called Asynchronously) as soon as the request is returned from the controller .
can you explain this scenario?
how do we in implement in the Jee application ?
This does not work.
Thanks man ! made my day
That one line saved my day. Thanks a lot for the good article
hello,
thanks a lot for this nice introduction. but there’s a single line of code missing in the applicationContext.xml file
xmlns:task=”http://www.springframework.org/schema/task” in .
without this line, you’re very much likely to get this error “The prefix “task” for element “task:annotation-driven” is not bound.” error.
happy coding
hi
i am a chinese spring developer
thx for your introduction
When used in combination with Hibernate, I run into org.hibernate.LazyInitializationException s
What’s the best way to create an open session in view for the Async method?
@stats
You can use an http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html as return value of an Async annotated method.
@stas When you say outcome , what do you exactly mean ?
The aysnc method will do job in background and exit. You can log the message when the method completes its execution.
Is there a way to get an outcome of the ansync method?
@Paramesh
Thanks for pointing out Paramesh. It should be Thread.sleep(5000).
I fixed it.
Hello ,
Its really good, I would like know about where did you specify the 5 seconds in above.. I notice that below one in above program ..
The program will not exit and after 5 second you will see .. but i noticed that in Thread.sleep(10000)..
Please advice
Excellent point Michael. Thanks a lot fro bringing this up.
Thanks for that post!
A small hint if you using async and annotation-based transactionhandling. You will need the async call before the method or facade with the @transactional otherwise the transactioncontext will not be expanded to the new thread….
greetings michael
thanks! short and sweet!
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!
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!
Thanks mKyong for mentioning the post. I appreciate it.
Thank you for your introduction. It’s really helpful.
oh, i like new info about Asynchronous. Thanks guys!