Google

May 30, 2013

Asynchronous processiong with Spring tutorial

Step 1: Create a maven based Java project of type jar. So, execute the following maven archetype command.

mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false




Step2: The above command would have created the maven skeleton. Add the "resources" folder under "src/main" to store the spring context file. Open the pom.xml file under the application and add the following depencies jar files. The cgilib version 2 is required for the spring 3 jars.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.mycompany.app</groupId>
 <artifactId>my-app</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>my-app</name>
 <url>http://maven.apache.org</url>
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>3.1.2.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>3.1.2.RELEASE</version>

  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-aop</artifactId>
   <version>3.1.2.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context-support</artifactId>
   <version>3.1.2.RELEASE</version>
  </dependency>

  <dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>2.2</version>
  </dependency>

 </dependencies>
</project>


Step 3: Add the applicationContext.xml spring file to "src/main/resources" folder.

<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="com.mycompany" />

 <task:annotation-driven />
 
</beans>


Step 4: Define the Java classes under src/main/java/com/mycompany/app folder as shown below.

Firstly the main class App.java that bootsraps spring via applicationContext.xml.

package com.mycompany.app;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Hello world!
 */
public class App
{
    public static void main(String[] args)
    {
        ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(new String[]
        {
            "applicationContext.xml"
        });
        
        AppService appService = (AppService) appContext.getBean("appService");
        
        appService.registerUser("skill");
    }
}


Secondly, the AppService.java class.

package com.mycompany.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class AppService
{
    
    @Autowired
    private EmailSender mailUtility;
    
    public void registerUser(String userName)
    {
        System.out.println(Thread.currentThread().getName());
        System.out.println("User registration for  " + userName + " complete");
        
        mailUtility.sendMail(userName);
        
        System.out.println("Registration Complete. Mail will be sent asynchronously.");
    }
}


Finally, EmailSender that runs asynchronously with the @Async annotation.

package com.mycompany.app;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class EmailSender
{
    @Async
    public void sendMail(String name)
    {
        
        System.out.println(Thread.currentThread().getName());
        System.out.println("started producing email content");
        
        try
        {
            Thread.sleep(3000); //to simulate email sending
            
        }
        catch (InterruptedException e)
        {
            
            e.printStackTrace();
        }
        
        System.out.println("email sending has been completed");
        
    }
}


The out put will be

main
User registration for  skill complete
Registration Complete. Mail will be sent asynchronously.
SimpleAsyncTaskExecutor-1
started producing email content
email sending has been completed


Q. How do you know that the EmailSender runs asynchronously on a separate thread?
A. Firstly, the Thread.currentThread().getName() was added to print the thread names and you can see that the AppService runs on the "main" thread and the EmailSender runs on the "SimpleAsyncTaskExecutor-1" thread. Secondly, the Thread.sleep(3000) was added to demonstrate that "Registration Complete. Mail will be sent asynchronously." gets printed without being blocked. If you rerun the App.java again by commenting out the "@Async" annotation in "EmailSender", you will get a different output as shown below.

main
User registration for  skill complete
main
started producing email content
email sending has been completed
Registration Complete. Mail will be sent asynchronously.


As you can see, there is only one thread named "main", and the order of the output is different.

Labels:

2 Comments:

Anonymous Anonymous said...

Great tutorial! It worked fine for me!!

11:41 PM, September 19, 2013  
Blogger Unknown said...

Glad that you found it useful.

3:09 AM, September 20, 2013  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home