diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java index 452f182957..aba9913b70 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractDelegatingConsumerEndpointParser.java @@ -17,6 +17,7 @@ package org.springframework.integration.config.xml; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; @@ -36,7 +37,7 @@ abstract class AbstractDelegatingConsumerEndpointParser extends AbstractConsumer @Override protected final BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getFactoryBeanClassName()); - BeanDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + BeanComponentDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); String ref = element.getAttribute(REF_ATTRIBUTE); String expression = element.getAttribute(EXPRESSION_ATTRIBUTE); boolean hasRef = StringUtils.hasText(ref); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java index 2ff7c34bd9..25efc3b9f7 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AbstractOutboundChannelAdapterParser.java @@ -59,7 +59,7 @@ public abstract class AbstractOutboundChannelAdapterParser extends AbstractChann AbstractBeanDefinition definition = this.parseConsumer(element, parserContext); if (definition == null) { parserContext.getReaderContext().error( - "Consumer parsing must return a BeanDefinition.", element); + "Consumer parsing must return a BeanComponentDefinition.", element); } String order = element.getAttribute("order"); if (StringUtils.hasText(order)) { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AggregatorParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AggregatorParser.java index 95d0b5c277..9a4a25b943 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AggregatorParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/AggregatorParser.java @@ -19,6 +19,7 @@ package org.springframework.integration.config.xml; import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; @@ -63,7 +64,7 @@ public class AggregatorParser extends AbstractConsumerEndpointParser { @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { - BeanDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + BeanComponentDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); String ref = element.getAttribute(REF_ATTRIBUTE); BeanDefinitionBuilder builder; diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java index fd8048ccaa..be84450b22 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java @@ -22,6 +22,7 @@ import org.w3c.dom.Element; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; @@ -180,24 +181,28 @@ public abstract class IntegrationNamespaceUtils { } } - public static BeanDefinition parseInnerHandlerDefinition(Element element, ParserContext parserContext){ + public static BeanComponentDefinition parseInnerHandlerDefinition(Element element, ParserContext parserContext){ // parses out inner bean definition for concrete implementation if defined List childElements = DomUtils.getChildElementsByTagName(element, "bean"); - BeanDefinition innerDefinition = null; + BeanComponentDefinition innerComponentDefinition = null; if (childElements != null && childElements.size() == 1){ Element beanElement = childElements.get(0); BeanDefinitionParserDelegate delegate = parserContext.getDelegate(); BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(beanElement); bdHolder = delegate.decorateBeanDefinitionIfRequired(beanElement, bdHolder); - innerDefinition = bdHolder.getBeanDefinition(); - BeanDefinitionReaderUtils.registerWithGeneratedName((AbstractBeanDefinition) innerDefinition, parserContext.getRegistry()); + BeanDefinition inDef = bdHolder.getBeanDefinition(); + String beanName = BeanDefinitionReaderUtils.generateBeanName(inDef, parserContext.getRegistry()); + innerComponentDefinition = new BeanComponentDefinition(inDef, beanName); + parserContext.registerBeanComponent(innerComponentDefinition); } String ref = element.getAttribute(REF_ATTRIBUTE); - Assert.isTrue(!(StringUtils.hasText(ref) && innerDefinition != null), "Ambiguous definition. Inner bean " + - (innerDefinition == null ? innerDefinition : innerDefinition.getBeanClassName()) + " declaration and \"ref\" " + ref + - " are not allowed together."); - return innerDefinition; + Assert.isTrue(!(StringUtils.hasText(ref) && innerComponentDefinition != null), "Ambiguous definition. Inner bean " + + (innerComponentDefinition == null + ? innerComponentDefinition + : innerComponentDefinition.getBeanDefinition().getBeanClassName()) + " declaration and \"ref\" " + ref + + " are not allowed together."); + return innerComponentDefinition; } } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java index 4b9789f642..4b35e8d1d6 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java @@ -18,6 +18,7 @@ package org.springframework.integration.config.xml; import org.w3c.dom.Element; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.ParserContext; @@ -32,9 +33,15 @@ public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingIn @Override protected String parseSource(Element element, ParserContext parserContext) { - String sourceRef = element.getAttribute("ref"); + BeanComponentDefinition bcDef = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + String sourceRef = null; + if (bcDef != null){ + sourceRef = bcDef.getBeanName(); + } else { + sourceRef = element.getAttribute("ref"); + } if (!StringUtils.hasText(sourceRef)) { - parserContext.getReaderContext().error("The 'ref' attribute is required.", element); + parserContext.getReaderContext().error("Either 'ref' attribute or inner-bean consumer definition is required.", element); } String methodName = element.getAttribute("method"); if (StringUtils.hasText(methodName)) { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java index 223db59448..fda6fa4ba0 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java @@ -16,15 +16,14 @@ package org.springframework.integration.config.xml; -import org.w3c.dom.Element; - -import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; 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.xml.ParserContext; import org.springframework.util.Assert; import org.springframework.util.StringUtils; +import org.w3c.dom.Element; /** * Parser for the <outbound-channel-adapter/> element. @@ -35,7 +34,13 @@ import org.springframework.util.StringUtils; public class MethodInvokingOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) { - String consumerRef = element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE); + BeanComponentDefinition consumerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + String consumerRef = null; + if (consumerDefinition == null){ + consumerRef = element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE); + } else { + consumerRef = consumerDefinition.getBeanName(); + } if (element.hasAttribute(IntegrationNamespaceUtils.METHOD_ATTRIBUTE)) { consumerRef = BeanDefinitionReaderUtils.registerWithGeneratedName( this.parseConsumer(element, parserContext), parserContext.getRegistry()); @@ -48,7 +53,7 @@ public class MethodInvokingOutboundChannelAdapterParser extends AbstractOutbound protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition( IntegrationNamespaceUtils.BASE_PACKAGE + ".handler.MethodInvokingMessageHandler"); - BeanDefinition innerHandlerDefinition = + BeanComponentDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); if (innerHandlerDefinition == null){ Assert.hasText(element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE), diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/ServiceActivatorParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/ServiceActivatorParser.java index 3b9a27e49a..e2a04eb519 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/ServiceActivatorParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/ServiceActivatorParser.java @@ -16,12 +16,11 @@ package org.springframework.integration.config.xml; -import org.w3c.dom.Element; - -import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; +import org.w3c.dom.Element; /** * Parser for the <service-activator> element. @@ -33,7 +32,7 @@ public class ServiceActivatorParser extends AbstractConsumerEndpointParser { @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { - BeanDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + BeanComponentDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( IntegrationNamespaceUtils.BASE_PACKAGE + ".handler.ServiceActivatingHandler"); diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-inner-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-inner-context.xml new file mode 100644 index 0000000000..73d734d2dd --- /dev/null +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-inner-context.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java index be29f7a040..9af9f9989a 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java @@ -39,16 +39,20 @@ import org.springframework.integration.message.StringMessage; /** * @author Mark Fisher + * @author Oleg Zhurakousky */ public class ChannelAdapterParserTests { private AbstractApplicationContext applicationContext; + private AbstractApplicationContext applicationContextInner; @Before public void setUp() { this.applicationContext = new ClassPathXmlApplicationContext( "ChannelAdapterParserTests-context.xml", this.getClass()); + this.applicationContextInner = new ClassPathXmlApplicationContext( + "ChannelAdapterParserTests-inner-context.xml", this.getClass()); } @After @@ -74,6 +78,23 @@ public class ChannelAdapterParserTests { message = channel.receive(100); assertNull(message); } + @Test + public void methodInvokingSourceStoppedByApplicationContextInner() { + String beanName = "methodInvokingSource"; + PollableChannel channel = (PollableChannel) this.applicationContextInner.getBean("queueChannel"); +// TestBean testBean = (TestBean) this.applicationContextInner.getBean("testBean"); +// testBean.store("source test"); + Object adapter = this.applicationContextInner.getBean(beanName); + assertNotNull(adapter); + assertTrue(adapter instanceof SourcePollingChannelAdapter); + this.applicationContextInner.start(); + Message message = channel.receive(1000); + assertNotNull(message); + //assertEquals("source test", testBean.getMessage()); + this.applicationContextInner.stop(); + message = channel.receive(100); + assertNull(message); + } @Test public void targetOnly() { @@ -180,4 +201,11 @@ public class ChannelAdapterParserTests { channelResolver.resolveChannelName("methodInvokingSource"); } + public static class SampleBean{ + private String message = "hello"; + + String getMessage() { + return message; + } + } }