Asynchronous service with spring @Async and Java Future
In this tutorial we use Java’s Future callback together with Spring @Async Thread execution. Whenever you want to make a time consuming task the best practice is to start this in a new thread and handle the service asynchronously. In this example we use Spring @Async to fire up a new thread and get the result in a later time.
Dependencies
We use spring @Async
for the asynchronous thread callbacks, so we need the following dependencies.
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.memorynotfound.spring.core</groupId>
<artifactId>async-service</artifactId>
<version>1.0.0-SNAPSHOT</version>
<url>https://memorynotfound.com</url>
<name>SPRING - ${project.artifactId}</name>
<properties>
<spring.version>4.1.7.RELEASE</spring.version>
</properties>
<dependencies>
<!-- spring dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
Bootstrapping Spring Application Java Configuration
Lets start by bootstrapping our spring application.
Info: Don’t forget to add the@EnableAsync
to the class. Like the name indicates: this enables the asynchronous processing. Without this annotation the methods annotated with the@Async
will not execute asynchronously.
package com.memorynotfound;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@EnableAsync
@Configuration
@ComponentScan("com.memorynotfound")
public class AppConfig {
}
Spring @Async Method invocation using Java’s Future
Here we create a simple long running method which is annotated with spring @Async
annotation. This is all it takes, together with the @EnableAsync
annotation to enable asynchronous processing with spring. We return a Future
which is one of the new libraries of Java 7. A Future represents the result of an asynchronous computation.
package com.memorynotfound;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
@Component
public class MailSender {
@Async
public Future<Boolean> sendMail() throws InterruptedException {
System.out.println("sending mail..");
Thread.sleep(1000 * 10);
System.out.println("sending mail completed");
return new AsyncResult<Boolean>(true);
}
}
Execute Spring @Async Methods
Finally lets put it all together and execute an example use case.
package com.memorynotfound;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class Main {
public static void main(String...args) throws InterruptedException, ExecutionException {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MailSender mailSender = context.getBean(MailSender.class);
System.out.println("about to run");
Future future = mailSender.sendMail();
System.out.println("this will run immediately.");
Boolean result = future.get();
System.out.println("mail send result: " + result);
}
}
Output
about to run
this will run immediately.
sending mail..
sending mail completed
mail send result: true