Friday, September 14, 2012

Spring @Async

I'll give a short demo a Spring's @Async annotation. Observe the following class (which is a Spring component):

@Component
public class SpringAsyncService {
 
 @Async
 public void writeSomethingASync() throws InterruptedException{
 
  System.err.println("Async start");

  Thread.sleep(10000);
  
  System.err.println("Async end");
 }

 @Async
 public Future<String> writeSomethingASyncResult() throws InterruptedException{
 
  System.err.println("Async with result start");
  
  Thread.sleep(10000);
  
  System.err.println("Async with result end");
  return new AsyncResult<String>("Returning from async with result");
 }


 public void writeSomethingSync(){
  System.err.println("Sync");
 }

}
The class has three methods of which the first two have the @Async annotation. Now observer the following class:

public class Main {

    public static void main(String... args) throws InterruptedException, ExecutionException {

     ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[] {
       "META-INF/spring/app-context.xml"});
     SpringAsyncService service = applicationContext.getBean(SpringAsyncService.class);
     
     Future<String> f = service.writeSomethingASyncResult();
     service.writeSomethingASync();
     service.writeSomethingSync();
     System.err.println(f.get());
         
    }
}
The above writes out the following (note that "Sync" is done before the async methods, even though it is called last):
Async with result start
Sync
Async start
Async end
Async with result end
Returning from async with result
If we put the System.err.println(f.get()) line right after the call to writeSomethingASyncResult then the output will be (as the main thread is waiting for the result of the asynchronous method):
Async with result start
Async with result end
Returning from async with result
Sync
Async start
Async end

Here is the configuration file. The important stuff is the task namespace and the annotation-driven tag:
<?xml version="1.0" encoding="UTF-8"?>
<beans 
xmlns="http://www.springframework.org/schema/beans"
xmlns:task="http://www.springframework.org/schema/task" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="org.saabye_pedersen.spring" />

 <task:annotation-driven />

</beans>