I have an application running under Spring Boot 1.2.3 that uses methods annotated with @Async.  To date it's been working properly.
After upgrading to Spring Boot 1.3.3, methods marked as @Async are not being called in a separate thread.
Here's a sample program that illustrates the issue:
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>
Under 1.2.3, the log statements in the start method show them as running in thread myTaskExecutor-1.  Under 1.3.3, the same logs show that they run in thread main.
Any idea what might be wrong here?
You need place your bean factory method in a other class annotated as @Configuration. Executor will be used for @Async method execution in this way.
@Configuration
@EnableAsync
public class AsyncConfig {
   @Bean(name = "myTaskExecutor")
   public ThreadPoolTaskExecutor myTaskExecutor() {
      return new ThreadPoolTaskExecutor();
   }
}
                        Injecting into configuration classes might be a challenge, I wouldn't recommend it especially if that class is also an actual bean. IMHO your class does too much. Next to that move the configuration of the ThreadPoolTaskExecutor where it belongs. 
Instead of autowiring create a @Bean method which returns a CommandLineRunner instead of you 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 cleanup your AsyncClass.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With