After upgrading application to Spring 2.1.0 I tried to use Hibernate asynchronously bootstrap, but when I'm adding a flag spring.data.jpa.repositories.bootstrap-mode=deferred to configuration then application throws error during startup:
Parameter 0 of method entityManagerFactory in org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration required a single bean, but 2 were found: - [ ] - applicationTaskExecutor: defined by method 'applicationTaskExecutor' in class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class] - taskScheduler: defined by method 'taskScheduler' in class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class]
Looks like Spring have trouble with finding unique AsyncTaskExecutor bean and both beans are coming from auto configuration. To make it work I excluded TaskExecutionAutoConfiguration:
@SpringBootApplication(exclude = {TaskExecutionAutoConfiguration.class})
@EnableScheduling
class MyApp {}
Thanks for the report. Looks like we've missed testing the async bootstrapping with scheduling enabled.
I also get a similar error when using @EnableWebSocketMessageBroker. It looks like the JpaRepositoriesAutoConfiguration expects exactly one AsyncTaskExecutor in the application.
Cause:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.core.task.AsyncTaskExecutor' available: expected single matching bean but found 4: clientInboundChannelExecutor,clientOutboundChannelExecutor,brokerChannelExecutor,messageBrokerTaskScheduler
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:217)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1217)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getIfAvailable(DefaultListableBeanFactory.java:1868)
at org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration.lambda$entityManagerFactoryBootstrapExecutorCustomizer$0(JpaRepositoriesAutoConfiguration.java:76)
at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.lambda$entityManagerFactoryBuilder$0(JpaBaseConfiguration.java:128)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1378)
at java.base/java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:395)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.base/java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
at org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.entityManagerFactoryBuilder(JpaBaseConfiguration.java:128)
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$b797f511.CGLIB$entityManagerFactoryBuilder$7(<generated>)
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$b797f511$$FastClassBySpringCGLIB$$4837111.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaConfiguration$$EnhancerBySpringCGLIB$$b797f511.entityManagerFactoryBuilder(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 83 more
@trevor-stedman that's a related but it is a different problem. I suspect the fix on this issue will fix yours as well though.
Related issue in Spring https://jira.spring.io/browse/SPR-17021
Essentially the new auto-configuration in 2.1 configures a TaskScheduler and a TaskExecutor. Unfortunately, both are implementing the AsyncTaskExecutor interface so we could fix this issue by narrowing down the type that we require.
There's not much we can use without using a very specific type so I suggest we fallback to applicationTaskExecutor if more than one instance exists. This is the standard TaskExecutor bean name that is now promoted.
Most helpful comment
Fixed by https://github.com/spring-projects/spring-boot/commit/830da28b8ccfe8babce441291716adf3ba161f4a