INT-3240: i-c-a-parser: Fix gen. MessageSource Id

JIRA: https://jira.springsource.org/browse/INT-3240

Spring Integration 3.0 introduced registration of `MessageSource`s as beans
with an `id` based on the adapter `id` or, as a fallback, generated from
the `MessageSource` class name and the suffix `.source`.
But since that bean wasn't registered as a bean with the generated name (because the suffix was added),
subsequent elements get the same source bean name. This meant that
several anonymous `inbound-channel-adapter` with the same type (`file:`, `ftp:`, `twitter:` etc.)
caused an issue, when the same `MessageSource` bean was used by several `SourcePollingChannelAdapter` beans.

Fix the issue for fallback name generation by using the `SourcePollingChannelAdapterFactoryBean` class name.
Since that is registered, the source will always get a unique name, regardless of whether an id is provided.
This commit is contained in:
Artem Bilan
2014-01-02 19:20:24 +02:00
committed by Gary Russell
parent b0c70ab519
commit 91f6265344
3 changed files with 38 additions and 5 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,13 +42,13 @@ public abstract class AbstractPollingInboundChannelAdapterParser extends Abstrac
if (source == null) {
parserContext.getReaderContext().error("failed to parse source", element);
}
BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SourcePollingChannelAdapterFactoryBean.class);
String channelAdapterId = this.resolveId(element, (AbstractBeanDefinition) source, parserContext);
String channelAdapterId = this.resolveId(element, adapterBuilder.getRawBeanDefinition(), parserContext);
String sourceBeanName = channelAdapterId + ".source";
parserContext.getRegistry().registerBeanDefinition(sourceBeanName, (BeanDefinition) source);
BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder
.genericBeanDefinition(SourcePollingChannelAdapterFactoryBean.class);
adapterBuilder.addPropertyReference("source", sourceBeanName);
adapterBuilder.addPropertyReference("outputChannel", channelName);
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "send-timeout");

View File

@@ -46,4 +46,23 @@
<beans:bean id="testBean" class="org.springframework.integration.config.TestBean"/>
<poller default="true" max-messages-per-poll="1" fixed-delay="100"/>
<channel id="channelAdapter1Channel">
<queue/>
</channel>
<channel id="channelAdapter2Channel">
<queue/>
</channel>
<beans:bean id="counter1" class="java.util.concurrent.atomic.AtomicInteger"/>
<beans:bean id="counter2" parent="counter1"/>
<inbound-channel-adapter channel="channelAdapter1Channel" ref="counter1" method="incrementAndGet"/>
<inbound-channel-adapter channel="channelAdapter2Channel" ref="counter2" method="incrementAndGet"/>
</beans:beans>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -280,6 +280,20 @@ public class ChannelAdapterParserTests {
new ClassPathXmlApplicationContext("InboundChannelAdapterInnerBeanWithExpression-fail-context.xml", this.getClass());
}
@Test
public void testMessageSourceUniqueIds() {
PollableChannel channel1 = this.applicationContext.getBean("channelAdapter1Channel", PollableChannel.class);
PollableChannel channel2 = this.applicationContext.getBean("channelAdapter2Channel", PollableChannel.class);
for (int i = 0; i < 10; i++) {
Message<?> message = channel1.receive(5000);
assertNotNull(message);
assertEquals(i + 1, message.getPayload());
message = channel2.receive(5000);
assertEquals(i + 1, message.getPayload());
}
}
public static class SampleBean {
private String message = "hello";