Description
Found it in 5.1.X Though I'm sure it affects other versions as well.
Bug report
consider
registerNullChannel method in org.springframework.integration.config.DefaultConfiguringBeanFactoryPostProcessor
private void registerNullChannel() {
if (this.beanFactory.containsBean(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
BeanDefinition nullChannelDefinition = null;
if (this.beanFactory.containsBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME)) {
nullChannelDefinition =
this.beanFactory.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
}
else {
BeanDefinitionRegistry parentBeanFactory =
(BeanDefinitionRegistry) this.beanFactory.getParentBeanFactory();
if (parentBeanFactory != null) {
nullChannelDefinition =
parentBeanFactory.getBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME);
}
}
if (nullChannelDefinition != null &&
!NullChannel.class.getName().equals(nullChannelDefinition.getBeanClassName())) {
throw new IllegalStateException("The bean name '" + IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME
+ "' is reserved.");
}
}
else {
this.registry.registerBeanDefinition(IntegrationContextUtils.NULL_CHANNEL_BEAN_NAME,
new RootBeanDefinition(NullChannel.class));
}
}
So what it does is first ask the beanFactory if the bean exists - this.beanFactory.containsBean
If you look at the code for this method you'll notice that it goes all the way up the spring context heirarchy looking for the method.
And if this method returns true, the bean is requested.
When it does not find it in the current bean factory it only checks the immediate parent factory for the bean - it does not roll all the way up the heirarchy in the way that the containsBean method does.
So when your nullChannel bean is in not in the immediate parent (e.g. it's in the parent of the parent) - this method will fail.
I'll try see if I can create a test case - though I suspect it might be simpler for me to just create a pull request that rolls up the heirarchy looking for the factory that does contain the bean. So call containsBeanDefinition on each parent until a true is returned and then call getBeanDefinition on that beanfactory.