Saturday, November 27, 2021

Spring @Async @EnableAsync Annotations - Asynchronous Method Support

In this post we’ll see Spring support for asynchronous method execution using @Async annotation and how to enable support for it using @EnableAsync if you are using Java configuration.

Spring @Async annotation

When a method is annotated with @Async annotation the invocation of that method will occur asynchronously. Which means the caller will return immediately upon invocation and the actual execution of the method will occur in a task that has been submitted to a Spring TaskExecutor.

Spring asynchronous method invocation example

For asynchronous method execution using @Async annotation in Spring framework following tasks are required.

  1. Enable scheduling annotations
  2. Define a TaskExecutor that will execute the method as a submitted task. In the example ThreadPoolTaskExecutor implementation of the TaskExecutor is used.
  3. Write a method annotated with @Async annotation.

Enable scheduling annotations using @EnableAsync annotation

To enable support for @Async annotation add @EnableAsync to one of your @Configuration classes. Also define a TaskExecutor.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
@ComponentScan(basePackages = "org.netjs.service")
public class AppConfig {
 @Bean
 public TaskExecutor threadPoolTaskExecutor() {
  ThreadPoolTaskExecutor ex = new ThreadPoolTaskExecutor();
  ex.setCorePoolSize(4);
  ex.setMaxPoolSize(6);
  ex.setQueueCapacity(10);
  ex.initialize();
  return ex;
 }
}
In case of XML configuration you can configure it as following using the task name space.
<?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: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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/task
    http://www.springframework.org/task/spring-task.xsd">
    <context:component-scan base-package="org.netjs.service" />
    
    <task:annotation-driven executor="taskExecutor" />
    <task:executor id="taskExecutor" pool-size="5" queue-capacity="10"/>
</beans>

Service with @Async annotated method

@Service
public class EmployeeService {
  @Async
  public CompletableFuture<Integer> getEmployeeCount(){
    int count = 0;
    Object obj = em.createQuery("SELECT COUNT(emp) FROM Employee emp").getSingleResult();
    if(obj instanceof Integer){
      count=(Integer)obj;
    }else if(obj instanceof Long){
      count=((Long)obj).intValue();
    }
    return CompletableFuture.completedFuture(count);
  }
}

Here we have a method that returns a value which has to be invoked asynchronously. Note that such methods are required to have a Future typed return value. @Async methods may not only declare a regular java.util.concurrent.Future return type but also Spring’s org.springframework.util.concurrent.ListenableFuture or, as of Spring 4.2, CompletableFuture in Java too.

You can also apply the @Async annotation to a void-returning method.

@Async
void doSomething() {
   // this will be executed asynchronously
}

Or to a method with argument(s)

@Async
void doSomething(String s) {
  // this will be executed asynchronously
}
To run the above example you can use the following code.
public class App {
  public static void main( String[] args ){
    AbstractApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    EmployeeService employeeService = context.getBean("employeeService", EmployeeService.class);
    CompletableFuture<Integer> cf = employeeService.getEmployeeCount();
    try {
      System.out.println("Count--" + cf.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    context.registerShutdownHook();
  }
}

If you are using XML Configuration not Java config then you may need to use ClassPathXmlApplicationContext in place of AbstractApplicationContext.

That's all for this topic Spring @Async @EnableAsync Annotations - Asynchronous Method Support. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring Email Scheduling Example Using Quartz Scheduler
  2. Spring MVC Generate Response as JSON Example
  3. Difference Between @Controller And @RestController Annotations in Spring
  4. Spring Transaction Management JDBC Example Using @Transactional Annotation
  5. @Required Annotation in Spring Framework

You may also like-

  1. Spring Bean Life Cycle
  2. Bean Definition Inheritance in Spring
  3. Autowiring Using Annotations in Spring
  4. RunTime Injection Using Spring Expression Language (SpEL)
  5. Lambda Expressions in Java 8
  6. Just In Time Compiler (JIT) in Java
  7. Searching Within a String Using indexOf(), lastIndexOf() And contains() Methods
  8. Uber Mode in Hadoop

No comments:

Post a Comment