@Async does not work after upgrading to Spring Download 1.3.3

I have an application under Spring Boot 1.2.3 that uses methods annotated with @Async . Today it works fine.

After upgrading to Spring Boot 1.3.3, methods marked as @Async do not call in a separate thread.

Here is an example program that illustrates the problem:

App.java:

 package test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; @Configuration @EnableAutoConfiguration @ComponentScan(basePackages = { "test" }) @EnableAsync public class App implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(App.class); @Autowired AsyncClass async; public static void main(String[] args) { SpringApplication.run(App.class, args); } public void run(String... arg0) throws Exception { log.info("in run"); async.start(); log.info("done run"); } } 

AsyncClass.java:

 package test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; @Component public class AsyncClass { private static final Logger log = LoggerFactory.getLogger(AsyncClass.class); @Async("myTaskExecutor") public void start() { log.info("in async task"); try { Thread.sleep(2000); } catch (InterruptedException e) { } log.info("done async task"); } @Bean public ThreadPoolTaskExecutor myTaskExecutor() { ThreadPoolTaskExecutor bean = new ThreadPoolTaskExecutor(); bean.setCorePoolSize(1); bean.setMaxPoolSize(1); bean.setQueueCapacity(10); bean.setThreadPriority(1); bean.setWaitForTasksToCompleteOnShutdown(true); return bean; } } 

pom.xml:

 <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>dbush</groupId> <artifactId>async-test</artifactId> <version>0.0.1-SNAPSHOT</version> <name>async-test</name> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>${java.version}</maven.compiler.source> <maven.compiler.target>${java.version}</maven.compiler.target> </properties> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <!-- this is the only line that differs --> <version>1.3.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project> 

In section 1.2.3, the log statements in the start method show that they are executed in the myTaskExecutor-1 thread. In section 1.3.3, the same logs show that they are running on the main thread.

Any idea what might be wrong here?

+6
source share
2 answers

You need to place your bean factory method in another class annotated as @Configuration. Thus, Executor will be used to execute the @Async method.

 @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "myTaskExecutor") public ThreadPoolTaskExecutor myTaskExecutor() { return new ThreadPoolTaskExecutor(); } } 
+2
source

Entering configuration classes can be a problem, I would not recommend it especially if this class is also an actual bean. IMHO your class does too much. Next to this, move the ThreadPoolTaskExecutor configuration where it belongs.

Instead of @Bean , create an @Bean method that returns a CommandLineRunner instead of implementing it.

 @SpringBootApplication @EnableAsync public class App { private static final Logger log = LoggerFactory.getLogger(App.class); public static void main(String[] args) { SpringApplication.run(App.class, args); } @Bean public CommandLineRunner runner(AsyncClass async) { return new CommandLineRunner() { public void run(String... arg0) throws Exception { log.info("in run"); async.start(); log.info("done run"); } }; } @Bean public ThreadPoolTaskExecutor taskExecutor() { ThreadPoolTaskExecutor bean = new ThreadPoolTaskExecutor(); bean.setCorePoolSize(1); bean.setMaxPoolSize(1); bean.setQueueCapacity(10); bean.setThreadPriority(1); bean.setWaitForTasksToCompleteOnShutdown(true); return bean; } } 

And of course, clear your AsyncClass .

+2
source

Source: https://habr.com/ru/post/1244689/


All Articles