diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelAdapterParser.java index 2c2d71f982..54a1050914 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelAdapterParser.java @@ -24,6 +24,7 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.MessagingConfigurationException; import org.springframework.integration.endpoint.InboundMethodInvokingChannelAdapter; import org.springframework.integration.endpoint.OutboundMethodInvokingChannelAdapter; import org.springframework.util.StringUtils; @@ -62,6 +63,7 @@ public class ChannelAdapterParser implements BeanDefinitionParser { String ref = element.getAttribute(REF_ATTRIBUTE); String method = element.getAttribute(METHOD_ATTRIBUTE); if (!StringUtils.hasText(ref) || !StringUtils.hasText(method)) { + throw new MessagingConfigurationException("'ref' and 'method' are both required"); } adapterDef.getPropertyValues().addPropertyValue("object", new RuntimeBeanReference(ref)); adapterDef.getPropertyValues().addPropertyValue("method", method); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/EndpointParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/EndpointParser.java index 6c82739396..a04077145f 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/EndpointParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/EndpointParser.java @@ -16,6 +16,9 @@ package org.springframework.integration.config; +import java.util.ArrayList; +import java.util.List; + import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -23,12 +26,15 @@ import org.w3c.dom.NodeList; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; +import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.MessagingConfigurationException; import org.springframework.integration.bus.ConsumerPolicy; import org.springframework.integration.endpoint.GenericMessageEndpoint; import org.springframework.integration.handler.DefaultMessageHandlerAdapter; +import org.springframework.integration.handler.MessageHandlerChain; import org.springframework.util.StringUtils; /** @@ -48,6 +54,14 @@ public class EndpointParser implements BeanDefinitionParser { private static final String DEFAULT_OUTPUT_CHANNEL_PROPERTY = "defaultOutputChannelName"; + private static final String HANDLER_ELEMENT = "handler"; + + private static final String REF_ATTRIBUTE = "ref"; + + private static final String METHOD_ATTRIBUTE = "method"; + + private static final String HANDLERS_PROPERTY = "handlers"; + private static final String HANDLER_REF_ATTRIBUTE = "handler-ref"; private static final String HANDLER_METHOD_ATTRIBUTE = "handler-method"; @@ -78,25 +92,7 @@ public class EndpointParser implements BeanDefinitionParser { if (StringUtils.hasText(defaultOutputChannel)) { endpointDef.getPropertyValues().addPropertyValue(DEFAULT_OUTPUT_CHANNEL_PROPERTY, defaultOutputChannel); } - String handlerRef = element.getAttribute(HANDLER_REF_ATTRIBUTE); - if (StringUtils.hasText(handlerRef)) { - String handlerMethod = element.getAttribute(HANDLER_METHOD_ATTRIBUTE); - if (StringUtils.hasText(handlerMethod)) { - BeanDefinition handlerAdapterDef = new RootBeanDefinition(DefaultMessageHandlerAdapter.class); - handlerAdapterDef.getPropertyValues().addPropertyValue(OBJECT_PROPERTY, new RuntimeBeanReference(handlerRef)); - handlerAdapterDef.getPropertyValues().addPropertyValue(METHOD_NAME_PROPERTY, handlerMethod); - String adapterBeanName = parserContext.getReaderContext().generateBeanName(handlerAdapterDef); - parserContext.registerBeanComponent(new BeanComponentDefinition(handlerAdapterDef, adapterBeanName)); - endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(adapterBeanName)); - } - else { - endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(handlerRef)); - } - } - String beanName = element.getAttribute(ID_ATTRIBUTE); - if (!StringUtils.hasText(beanName)) { - beanName = parserContext.getReaderContext().generateBeanName(endpointDef); - } + List childHandlerRefs = new ArrayList(); NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node child = childNodes.item(i); @@ -107,8 +103,49 @@ public class EndpointParser implements BeanDefinitionParser { endpointDef.getPropertyValues().addPropertyValue( CONSUMER_POLICY_PROPERTY, new RuntimeBeanReference(consumerBeanName)); } + else if (HANDLER_ELEMENT.equals(localName)) { + String ref = ((Element) child).getAttribute(REF_ATTRIBUTE); + String method = ((Element) child).getAttribute(METHOD_ATTRIBUTE); + childHandlerRefs.add(this.parseHandlerAdapter(ref, method, parserContext)); + } } } + if (childHandlerRefs.size() > 0) { + if (childHandlerRefs.size() == 1) { + endpointDef.getPropertyValues().addPropertyValue( + HANDLER_PROPERTY, new RuntimeBeanReference(childHandlerRefs.get(0))); + } + else { + RootBeanDefinition handlerChainDef = new RootBeanDefinition(MessageHandlerChain.class); + List handlerList = new ManagedList(); + for (String ref : childHandlerRefs) { + handlerList.add(new RuntimeBeanReference(ref)); + } + handlerChainDef.getPropertyValues().addPropertyValue(HANDLERS_PROPERTY, handlerList); + String chainBeanName = parserContext.getReaderContext().generateBeanName(handlerChainDef); + parserContext.registerBeanComponent(new BeanComponentDefinition(handlerChainDef, chainBeanName)); + endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(chainBeanName)); + } + } + String handlerRef = element.getAttribute(HANDLER_REF_ATTRIBUTE); + if (StringUtils.hasText(handlerRef)) { + if (childHandlerRefs.size() > 0) { + throw new MessagingConfigurationException( + "The 'handler-ref' attribute is only supported when no 'handler' child elements are present"); + } + String handlerMethod = element.getAttribute(HANDLER_METHOD_ATTRIBUTE); + if (StringUtils.hasText(handlerMethod)) { + String adapterBeanName = this.parseHandlerAdapter(handlerRef, handlerMethod, parserContext); + endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(adapterBeanName)); + } + else { + endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(handlerRef)); + } + } + String beanName = element.getAttribute(ID_ATTRIBUTE); + if (!StringUtils.hasText(beanName)) { + beanName = parserContext.getReaderContext().generateBeanName(endpointDef); + } parserContext.registerBeanComponent(new BeanComponentDefinition(endpointDef, beanName)); return endpointDef; } @@ -124,4 +161,13 @@ public class EndpointParser implements BeanDefinitionParser { return beanName; } + private String parseHandlerAdapter(String handlerRef, String handlerMethod, ParserContext parserContext) { + BeanDefinition handlerAdapterDef = new RootBeanDefinition(DefaultMessageHandlerAdapter.class); + handlerAdapterDef.getPropertyValues().addPropertyValue(OBJECT_PROPERTY, new RuntimeBeanReference(handlerRef)); + handlerAdapterDef.getPropertyValues().addPropertyValue(METHOD_NAME_PROPERTY, handlerMethod); + String adapterBeanName = parserContext.getReaderContext().generateBeanName(handlerAdapterDef); + parserContext.registerBeanComponent(new BeanComponentDefinition(handlerAdapterDef, adapterBeanName)); + return adapterBeanName; + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd b/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd index 63df6745ee..42ffd58128 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-1.0.xsd @@ -97,6 +97,7 @@ + @@ -118,4 +119,16 @@ + + + + + Defines a handler. + + + + + + + \ No newline at end of file diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/MessageHandlerChain.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/MessageHandlerChain.java index 7e4da58c06..569354d995 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/MessageHandlerChain.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/MessageHandlerChain.java @@ -46,6 +46,11 @@ public class MessageHandlerChain implements MessageHandler { this.handlers.add(index, handler); } + public void setHandlers(List handlers) { + this.handlers.clear(); + this.handlers.addAll(handlers); + } + public Message handle(Message message) { for (MessageHandler next : handlers) { message = next.handle(message);