Added support for the "method" attribute on the <channel-adapter/> element in order to create MethodInvokingSource or MethodInvokingTarget instances.

This commit is contained in:
Mark Fisher
2008-08-19 22:51:41 +00:00
parent 1a92320ef7
commit 42e7a6bffa
5 changed files with 76 additions and 2 deletions

View File

@@ -23,12 +23,15 @@ import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.endpoint.InboundChannelAdapter;
import org.springframework.integration.endpoint.OutboundChannelAdapter;
import org.springframework.integration.handler.MethodInvokingTarget;
import org.springframework.integration.message.MethodInvokingSource;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -57,12 +60,16 @@ public class ChannelAdapterParser extends AbstractBeanDefinitionParser {
String source = element.getAttribute("source");
String target = element.getAttribute("target");
String channelName = element.getAttribute("channel");
String methodName = element.getAttribute("method");
Element pollerElement = DomUtils.getChildElementByTagName(element, "poller");
BeanDefinitionBuilder adapterBuilder = null;
if (StringUtils.hasText(source)) {
if (StringUtils.hasText(target)) {
throw new ConfigurationException("both 'source' and 'target' are not allowed, provide only one");
}
if (StringUtils.hasText(methodName)) {
source = parseMethodInvokingAdapter(source, methodName, MethodInvokingSource.class, parserContext.getRegistry());
}
adapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(InboundChannelAdapter.class);
if (pollerElement != null) {
String pollerBeanName = IntegrationNamespaceUtils.parsePoller(source, pollerElement, parserContext);
@@ -80,6 +87,9 @@ public class ChannelAdapterParser extends AbstractBeanDefinitionParser {
}
}
else if (StringUtils.hasText(target)) {
if (StringUtils.hasText(methodName)) {
target = this.parseMethodInvokingAdapter(target, methodName, MethodInvokingTarget.class, parserContext.getRegistry());
}
adapterBuilder = BeanDefinitionBuilder.genericBeanDefinition(OutboundChannelAdapter.class);
adapterBuilder.addPropertyReference("target", target);
if (pollerElement != null) {
@@ -103,6 +113,13 @@ public class ChannelAdapterParser extends AbstractBeanDefinitionParser {
return adapterBuilder.getBeanDefinition();
}
private String parseMethodInvokingAdapter(String objectRef, String methodName, Class<?> type, BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
builder.addPropertyReference("object", objectRef);
builder.addPropertyValue("methodName", methodName);
return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), registry);
}
private String createDirectChannel(Element element, ParserContext parserContext) {
String channelId = element.getAttribute("id");
if (!StringUtils.hasText(channelId)) {

View File

@@ -166,6 +166,7 @@
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="source" type="xsd:string"/>
<xsd:attribute name="target" type="xsd:string"/>
<xsd:attribute name="method" type="xsd:string"/>
<xsd:attribute name="channel" type="xsd:string"/>
</xsd:complexType>
</xsd:element>

View File

@@ -7,10 +7,20 @@
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-core-1.0.xsd">
<message-bus/>
<message-bus auto-startup="false"/>
<queue-channel id="queueChannel" capacity="10"/>
<channel-adapter id="outboundWithImplicitChannel" target="target"/>
<channel-adapter id="methodInvokingTarget" target="testBean" method="store"/>
<channel-adapter id="methodInvokingSource" source="testBean" method="getMessage" channel="queueChannel">
<poller period="10000" max-messages-per-poll="1"/>
</channel-adapter>
<beans:bean id="target" class="org.springframework.integration.config.TestTarget"/>
<beans:bean id="testBean" class="org.springframework.integration.config.TestBean"/>
</beans:beans>

View File

@@ -17,8 +17,8 @@
package org.springframework.integration.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -26,6 +26,8 @@ import org.junit.Test;
import org.springframework.integration.bus.MessageBus;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.endpoint.InboundChannelAdapter;
import org.springframework.integration.endpoint.OutboundChannelAdapter;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.StringMessage;
@@ -44,6 +46,7 @@ public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests
Object channel = this.applicationContext.getBean(beanName);
assertTrue(channel instanceof DirectChannel);
MessageBus bus = (MessageBus) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
bus.start();
assertNotNull(bus.lookupChannel(beanName));
Object adapter = bus.lookupEndpoint(beanName + ".adapter");
assertNotNull(adapter);
@@ -54,6 +57,45 @@ public class ChannelAdapterParserTests extends AbstractJUnit4SpringContextTests
assertTrue(((MessageChannel) channel).send(message));
assertNotNull(target.getLastMessage());
assertEquals(message, target.getLastMessage());
bus.stop();
}
@Test
public void methodInvokingTarget() {
String beanName = "methodInvokingTarget";
Object channel = this.applicationContext.getBean(beanName);
assertTrue(channel instanceof DirectChannel);
MessageBus bus = (MessageBus) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
bus.start();
assertNotNull(bus.lookupChannel(beanName));
Object adapter = bus.lookupEndpoint(beanName + ".adapter");
assertNotNull(adapter);
assertTrue(adapter instanceof OutboundChannelAdapter);
TestBean testBean = (TestBean) this.applicationContext.getBean("testBean");
assertNull(testBean.getMessage());
Message<?> message = new StringMessage("target test");
assertTrue(((MessageChannel) channel).send(message));
assertNotNull(testBean.getMessage());
assertEquals("target test", testBean.getMessage());
bus.stop();
}
@Test
public void methodInvokingSource() {
String beanName = "methodInvokingSource";
PollableChannel channel = (PollableChannel) this.applicationContext.getBean("queueChannel");
MessageBus bus = (MessageBus) this.applicationContext.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
assertNull(bus.lookupChannel(beanName));
Object adapter = bus.lookupEndpoint(beanName);
assertNotNull(adapter);
assertTrue(adapter instanceof InboundChannelAdapter);
TestBean testBean = (TestBean) this.applicationContext.getBean("testBean");
testBean.store("source test");
bus.start();
Message<?> message = channel.receive(1000);
assertNotNull(message);
assertEquals("source test", testBean.getMessage());
bus.stop();
}
}

View File

@@ -30,6 +30,10 @@ public class TestBean {
private String replyMessageText = null;
public TestBean() {
this(1);
}
public TestBean(int countdown) {
this.latch = new CountDownLatch(countdown);
}