May 5, 2010

How To Use @Async in Spring Web Application?

I decided to give the @Async annotation a try! The recently added @Async annotation in the Spring Framework 3.0 seems to be an easy fit for applications that would require asynchrous calls to be invoked while the application is running or deployed! Here is a sample code that can help you with making your @Async annotation work with ease!
  1. As the first step, you have to incorporate the schema location detail and the xmlns detail for the task tag in Spring framework. The xmlns configuration details that you need to include is:
    xmlns:task=http://www.springframework.org/schema/task
  2. The schema location configuration details that you need to include in your application context includes


    http://www.springframework.org/schema/task  
    http://www.springframework.org/schema/task/spring-task-3.0.xsd
    
  3. Next, make Spring container understand that you are going to invoke asynchrous tasks that are annotation driven. So, remember to add the following line in your applicationContext.xml file.


    <br /><task:annotation-driven><br />
  4. After this, check your configuration xml file to ensure that you have implemented the context scanning on the code package where you are going to define the asynchronous jobs that you expect to be run by the spring framework. Let us say, we have a package org.webapp.services.tasks where we are going to have a class that would have all the methods annotated with @Async here and these would in turn be invoked by the scheduler. Then, ensure that you have this package as a part of the component scanning tag within the configuration xml file as follows:


    <br /><context:component-scan base-package="org.webapp.services.tasks"><br />
  5. Now, we are almost complete with the changes in the configuration files. Next, let us go ahead with a class that would have methods annotated with @Async which are in turn the asynchronous tasks that would be invoked within our application. Remember, as discussed earlier, this class needs to be in org.webapp.services.tasks package. Let us refer to this class as MyScheduler.java. The code for this class would look something like:


    <br />package org.test.common.utils.Tasks;<br />import java.util.Date;<br />import org.springframework.scheduling.annotation.Async;<br />import org.springframework.transaction.annotation.Transactional;<br />import org.springframework.stereotype.Component;<br />@Component<br />public class MyScheduler implements Scheduler{<br />@Transactional(readOnly = false)<br />@Async<br />public void testTask() {<br />System.out.println("Starting to process the task at " + new Date()); <br />}<br />}<br />
  6. And that is it! You are done. The @Async tells the spring container that the method underneath is an asynchronous task that would be invoked within the application. You can call this method from any class using the snippet as given below:


    <br />@Autowired<br />private Scheduler s;<br /><br /> s.newTask();<br />
  7. Further, when you use @Async you can return parameters from those methods and that should be Future typed. Say Future etc! That is unbelievable. Even if you want to update the db, you can go ahead and get the current session and process this method within a transaction to make db updates on a periodical basis.
If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!



4 comments:

  1. I am able to get the async functionality to work but when I attempt to make a database call it stalls. I am using a service layer that calls a dao layer. The dao method is called but once it tries to get data from the db it hangs (query.list())

    ReplyDelete
  2. sorry for the delay! If you still have the issue, can you paste your code here. This (the hang) should never happen!

    ReplyDelete
  3. Me too. I got a "no session or session was closed" :(

    ReplyDelete
  4. That's because you can't have @Transactional and @Async on the same method.

    ReplyDelete