-1

I am trying async process in my code. i written code like below. But async process is not working. Thread name '' itself not showing in logs. It looks Service class is not looking bean 'asyncExecutor'. What i am missing here.

@SpringBootApplication
@EnableAsync
public class  MyMainApplication {

    @Bean(name = "asyncExecutor")
    public Executor asyncExecutor() {
          ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(3);
            executor.setMaxPoolSize(3);
            executor.setQueueCapacity(100);
            executor.setThreadNamePrefix("AsynchThread-");
            executor.initialize();
            return executor; 
    }
    
    public static void main(String[] args) {
        SpringApplication.run(MyMainApplication.class, args);
    }

}

Service Class

public void getSampleDetails(String param1, String param2) {
    log.info("Inside - getSampleDetails");
    CompletableFuture<Map<String, String>> sampleMap1 = null;
    CompletableFuture<Map<String,  String>> sampleMap2 = null;
    CompletableFuture<Map<String,  String>> sampleMap3 = null;
    sampleMap1 = getSampleMap1(param1, param2);
    sampleMap2 = getSampleMap2(param1, param2);
    sampleMap3 = getSampleMap3(param1, param2);         
    // Wait until they are all done
    CompletableFuture.allOf(sampleMap1, sampleMap2, sampleMap3).join();         
}
@Async("asyncExecutor")
    public CompletableFuture<Map<String, String>> getSampleMap1(String param1, String param2) throws InterruptedException {
    System.out.println("Inside  Method1");
    ..
    ..
    }   

@Async("asyncExecutor")
    public CompletableFuture<Map<String, String>> getSampleMap2(String param1, String param2) throws InterruptedException {
    System.out.println("Inside  Method2");
    ..
    ..
    }

@Async("asyncExecutor")
    public CompletableFuture<Map<String, String>> getSampleMap3(String param1, String param2) throws InterruptedException {
    System.out.println("Inside  Method3");
    ..
    ..
    }   

Thread name is not displayed and async process is not happening logs:

[           main]o.s.s.concurrent.ThreadPoolTaskExecutor   Initializing ExecutorService
[           main]o.s.s.concurrent.ThreadPoolTaskExecutor   Initializing ExecutorService 'asyncExecutor1'
[           main]o.s.s.c.ThreadPoolTaskScheduler           Initializing ExecutorService 'taskScheduler'
[           main]o.s.b.w.embedded.tomcat.TomcatWebServer   Tomcat started on port(s): 32182 (http) with context path '/myapplication'
[           main]MyMainApplication  Started MyMainApplication in 46.662 seconds (JVM running for 48.024)
 [exec-1]e-myapplication]  Initializing Spring DispatcherServlet 'dispatcherServlet'
  [exec-1]o.s.web.servlet.DispatcherServlet         Initializing Servlet 'dispatcherServlet'
  [exec-1]o.s.web.servlet.DispatcherServlet         Completed initialization in 8 ms
  [exec-1]Inside - getSampleDetails
  [exec-1]Inside  Method1
  [exec-1]Inside  Method2
  [exec-1]Inside  Method3 
slj
  • 65
  • 10
  • Are you invoking the `@Async`-annotated method from another method of the same class? If so, then see https://stackoverflow.com/questions/29284008/spring-boot-async-method-in-controller-is-executing-synchronously – Chin Huang Jan 21 '22 at 01:30
  • yes. i am calling 3 methods which has to be executed async and results should return in calling method. I didnt understand this answer from above link<<"The easiest fix is to put the @Async method in another @Bean.">> – slj Jan 21 '22 at 01:46

1 Answers1

0

When spring scans the bean, it will scan whether the @Async annotation is included on the method. If it is included, spring will dynamically generate a subclass (ie proxy class, proxy) for the bean, and the proxy class inherits the original bean. At this time, when the annotated method is called, it is actually called by the proxy class, and the proxy class adds asynchronous effects when it is called. However, if this annotated method is called by other methods in the same class, the method call does not go through the proxy class, but directly through the original bean, so there is no asynchronous effect, we see The phenomenon is that the @Async annotation is invalid.

You can try something like this:

  1. the call and task should be placed in different classes.
  2. Add annotation in startup class:@EnableAspectJAutoProxy(exposeProxy = true)
  3. In the Service Manager, use AopContext.currentProxy() to obtain the proxy class of the Service, and then call the transaction method to force through the proxy class to activate the transaction aspect.
chasing fish
  • 114
  • 3