After upgrading from Spring Boot 2.6.1 to 2.6.2 the following configuration does not work anymore:

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class AsyncExecutionConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(1);
        executor.setMaxPoolSize(2);
        executor.setThreadNamePrefix("SkyAsync");
        executor.initialize();
        return executor;
    }

    @Bean
    public TaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(2);
        scheduler.setThreadNamePrefix("SkyScheduled");
        return scheduler;
    }
}

Application startup fails with the following exception:

Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskScheduler' defined in class path resource [de/hhla/sky/app/configuration/async/AsyncExecutionConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.TaskScheduler]: Illegal arguments to factory method 'taskScheduler'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class

Turning back to Spring Boot 2.6.1 fixes the issue

Alternately splitting the @Configuration into two classes also fixes the issue:

import java.util.concurrent.Executor;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
public class AsyncExecutionConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(1);
        executor.setMaxPoolSize(2);
        executor.setThreadNamePrefix("SkyAsync");
        executor.initialize();
        return executor;
    }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class TaskSchedulerConfiguration {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(2);
        scheduler.setThreadNamePrefix("SkyScheduled");
        return scheduler;
    }
}

The complete stacktrace looks like:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'taskScheduler' defined in class path resource [de/hhla/sky/app/configuration/async/AsyncExecutionConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.TaskScheduler]: Illegal arguments to factory method 'taskScheduler'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.14.jar:5.3.14]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.14.jar:5.3.14]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.2.jar:2.6.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.2.jar:2.6.2]
    at de.wps.dronecontrol.ControlServerApplication.main(ControlServerApplication.java:27) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.scheduling.TaskScheduler]: Illegal arguments to factory method 'taskScheduler'; args: ; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:172) ~[spring-beans-5.3.14.jar:5.3.14]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.14.jar:5.3.14]
    ... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.14.jar:5.3.14]
    ... 20 common frames omitted

EDIT: Added fix with two separate @Configuration classes

Comment From: Johannes-Rost

I tried to clarify the tilte of the issue

Comment From: Johannes-Rost

Seems to be related to changes made in org.springframework:spring-context:5.3.14 because using Spring Boot 2.6.2 with org.springframework:spring-context:5.3.13also fixes the issue.

Maybe this is a bug in Spring Framework?

Comment From: shu-wen-yu

Having the same issue while upgrading Spring Boot from 2.5.6 to 2.5.8. In our app, Sleuth's TraceAsyncCustomAutoConfiguration class wraps AsyncConfigurer with LazyTraceAsyncCustomizer, and then beans declared in an AsyncConfigurer are created with an instance of a LazyTraceAsyncCustomizer causing the exception. Moving the beans declaration outside AsyncConfigurer seem working

Comment From: wilkinsona

@Johannes-Rost I cannot reproduce the problem you've described using the snippets that you have provided. I guess there's something else in your app that you haven't described that's contributing to the problem. Please provide a complete yet minimal sample that reproduces the problem. You can share such a sample with us by zipping it up and attaching it to this issue or by pushing it to a separate repository on GitHub.

Comment From: Johannes-Rost

Hi @wilkinsona, just like @shu-wen-yu we also use Sleuth in our application. Maybe this is the missing part. If this is not sufficient I can put together a sample.

Comment From: wilkinsona

Thanks. Adding Sleuth was enough to reproduce the problem.

As far as I can tell, a change in Spring Framework 5.3.14 has exposed a problem in Spring Cloud Sleuth. It contains a bean post processor that will change the type of any AsyncConfigurer bean to wrap it with a LazyTraceAsyncCustomizer. The change in Framework means that this type change occurs before the taskScheduler() @Bean method is called. When it is then called it fails as the Method belongs to the AsyncExecutionConfiguration class but the bean instance is now a LazyTraceAsyncCustomizer.

I think this'll have to be fixed in Sleuth but I'd like to verify with @snicoll first.

Comment From: snicoll

Thanks for having a look Andy. I agree with the analysis here, the replacement in Sleuth is quite invasive. I am happy to adapt based on what Sleuth would need. @marcingrzejszczak can you please have a look? We can't transfer this issue as Spring Cloud Sleuth is in a separate org.

Comment From: wilkinsona

I think this needs to be addressed in Sleuth (and possibly Framework) so I've opened https://github.com/spring-cloud/spring-cloud-sleuth/issues/2100.