Since upgrading to Spring Boot 1.4 I've noticed that all of my microservices that override the primary ConnectionFactory AND create a secondary ConnectionFactory stopped working due to a NoSuchBeanDefinitionException.
@Bean(name = "pcConnectionFactory")
ConnectionFactory pcConnectionFactory(RabbitProperties config) throws Exception {
..
}
@Bean
@Primary
ConnectionFactory connectionFactory(RabbitProperties config) throws Exception {
..
}
@Bean
@Primary
ConnectionFactory connectionFactory(RabbitProperties config) throws Exception {
..
}
@Bean(name = "pcConnectionFactory")
ConnectionFactory pcConnectionFactory(RabbitProperties config) throws Exception {
..
}
Stack Trace:
Caused by: org.springframework.context.ApplicationContextException: Failed to start bean 'outputBindingLifecycle'; nested exception is java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration$RabbitTemplateConfiguration.rabbitTemplate
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:176)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:874)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:144)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 24 more
Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration$RabbitTemplateConfiguration.rabbitTemplate
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:64)
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:102)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:178)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:140)
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:116)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:333)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:98)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134)
at org.springframework.cloud.stream.binder.DefaultBinderFactory.getBinder(DefaultBinderFactory.java:185)
at org.springframework.cloud.stream.binding.ChannelBindingService.getBinderForChannel(ChannelBindingService.java:142)
at org.springframework.cloud.stream.binding.ChannelBindingService.bindProducer(ChannelBindingService.java:104)
at org.springframework.cloud.stream.binding.BindableProxyFactory.bindOutputs(BindableProxyFactory.java:206)
at org.springframework.cloud.stream.binding.OutputBindingLifecycle.start(OutputBindingLifecycle.java:57)
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:173)
... 38 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'pcConnectionFactory' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:702)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getPrimaryBeans(OnBeanCondition.java:234)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.hasSingleAutowireCandidate(OnBeanCondition.java:227)
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:97)
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47)
... 58 more
No bean named 'pcConnectionFactory' is defined
That doesn't sound legit to me. It looks like something is looking for a bean with that name and Spring Boot won't do that. Can you share a sample that reproduces the problem?
That doesn't sound legit to me
Couldn't agree more but after removing all references to pcConnectionFactory the same error kept coming up. I've created a really basic sample that reproduces the problem.
The zip file attachment here never works for me, so I've dropped the zip file with the sample here:
Location #1
Location #2
@chrisdadej all the Spring Cloud stuff is really polluting the sample. I've taken your class, added it to a Spring Boot 1.4 project created from start.spring.io and it didn't throw any issue. I think the issue is a bit more complicated. I can't reproduce and I have no idea where that lookup on your named connection factory is coming from. But it doesn't seem to be in Spring Boot.
Can you try to simplify your sample a bit? Maybe the issue is in another project.
It looks like an incompatibility between Spring Boot 1.4 and Spring Cloud Brixton.
Switching out:
compile "org.springframework.cloud:spring-cloud-starter-bus-amqp:${springCloudStarterVersion}"
for:
compile "org.springframework.amqp:spring-rabbit:1.6.1.RELEASE"
works as expected.
I'm assuming you were able to replicate the issue as is with my sample? You just weren't able to replicate it after taking out the Spring Cloud components.
I can post this to the Spring Cloud team for them to have a look at but there's definitely been a change made in 1.4 that isn't backwards compatible.
@chrisdadej the cross post is far from ideal. I am closing this one for now, let's see what the spring cloud team says.
I ran into the same issue as Chrisdadej. I have an application with multiple Rabbit ConnectionFactory beans and it resulted in a NoSuchBeanDefinitionException.
I think the problem is with spring-boot-autoconfigure project and not with spring-cloud. I was able to debug the problem to OnBeanCondition class in spring-boot-autoconfigure project.
First of all, ConditionalOnSingleCandidate(ConnectionFactory.class) (鹿) annotation was added to rabbitTemplate bean definition in org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration$RabbitTemplateConfiguration class as part of commit 9c73312.
@Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class)鹿
@ConditionalOnMissingBean(RabbitTemplate.class)
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
...
return rabbitTemplate;
}
When there are multiple connection factories, evaluation of ConditionalOnSingleCandidate fails to find any beans of type ConnectionFactory.
org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchingBeans(ConditionContext, BeanSearchSpec) (虏) method checks for matching bean definitions of type ConnectionFactory in the supplied beanFactory and the parent beanFactory references.
However OnBeanCondition.hasSingleAutowireCandidate(ConfigurableListableBeanFactory beanFactory, List
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
StringBuilder matchMessage = new StringBuilder();
if (metadata.isAnnotated(ConditionalOnBean.class.getName())) {
BeanSearchSpec spec = new BeanSearchSpec(context, metadata,
ConditionalOnBean.class);
List<String> matching = getMatchingBeans(context, spec);
if (matching.isEmpty()) {
return ConditionOutcome
.noMatch("@ConditionalOnBean " + spec + " found no beans");
}
matchMessage.append("@ConditionalOnBean ").append(spec)
.append(" found the following ").append(matching);
}
if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) {
BeanSearchSpec spec = new SingleCandidateBeanSearchSpec(context, metadata,
ConditionalOnSingleCandidate.class);
*** List<String> matching = getMatchingBeans(context, spec); 虏
if (matching.isEmpty()) {
return ConditionOutcome.noMatch(
"@ConditionalOnSingleCandidate " + spec + " found no beans");
}
*** else if (!hasSingleAutowireCandidate(context.getBeanFactory(), matching)) { 鲁
return ConditionOutcome.noMatch("@ConditionalOnSingleCandidate " + spec
+ " found no primary candidate amongst the" + " following "
+ matching);
}
matchMessage.append("@ConditionalOnSingleCandidate ").append(spec)
.append(" found a primary candidate amongst the following ")
.append(matching);
}
if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {
BeanSearchSpec spec = new BeanSearchSpec(context, metadata,
ConditionalOnMissingBean.class);
List<String> matching = getMatchingBeans(context, spec);
if (!matching.isEmpty()) {
return ConditionOutcome.noMatch("@ConditionalOnMissingBean " + spec
+ " found the following " + matching);
}
matchMessage.append(matchMessage.length() == 0 ? "" : " ");
matchMessage.append("@ConditionalOnMissingBean ").append(spec)
.append(" found no beans");
}
return ConditionOutcome.match(matchMessage.toString());
}
This issue is preventing me from upgrading to 1.4.0.RELEASE of spring-boot.
@chrisdadej @snicoll could this issue be reopened?
@buwi can you share a sample that reproduces the problem please?
@snicoll I have created a sample SpringBoot application and posted it here
Thanks.
Most helpful comment
@snicoll I have created a sample SpringBoot application and posted it here
Thanks.