Marketplace for Content, Tests and Assessment
 
 
Home > Programming / tutorials > Asynchronous method invocation in Spring 3.0

Asynchronous method invocation in Spring 3.0

January 13th, 2010 Vinay Leave a comment Go to comments

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

  1. January 15th, 2010 at 16:03 | #1

    oh, i like new info about Asynchronous. Thanks guys!

  2. Dai bang Canh cut
    January 17th, 2010 at 21:42 | #2

    Thank you for your introduction. It’s really helpful.

  3. January 18th, 2010 at 21:56 | #3

    Thanks mKyong for mentioning the post. I appreciate it.

  4. Jijik
    February 17th, 2010 at 03:16 | #4

    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!

  5. Jijik
    February 17th, 2010 at 04:18 | #5

    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!

  6. Genie
    June 10th, 2010 at 10:04 | #6

    thanks! short and sweet!

  7. Michael
    August 4th, 2010 at 04:13 | #7

    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

  8. August 4th, 2010 at 06:56 | #8

    Excellent point Michael. Thanks a lot fro bringing this up.

  9. Paramesh
    August 4th, 2010 at 22:18 | #9

    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

  10. August 4th, 2010 at 23:06 | #10

    @Paramesh
    Thanks for pointing out Paramesh. It should be Thread.sleep(5000).
    I fixed it.

  1. January 15th, 2010 at 21:01 | #1
  2. January 17th, 2010 at 02:31 | #2
  3. January 18th, 2010 at 05:37 | #3
  4. January 18th, 2010 at 21:38 | #4
Get Adobe Flash playerPlugin by wpburn.com wordpress themes