diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java index 96d12dd21a..c7f627dd91 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java @@ -61,7 +61,6 @@ public class IntegrationNamespaceHandler extends AbstractIntegrationNamespaceHan registerBeanDefinitionParser("poller", new PollerParser()); registerBeanDefinitionParser("annotation-config", new AnnotationConfigParser()); registerBeanDefinitionParser("application-event-multicaster", new ApplicationEventMulticasterParser()); - registerBeanDefinitionParser("scheduled-producer", new ScheduledProducerParser()); registerBeanDefinitionParser("publishing-interceptor", new PublishingInterceptorParser()); registerBeanDefinitionParser("channel-interceptor", new GlobalChannelInterceptorParser()); registerBeanDefinitionParser("converter", new ConverterParser()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java index 9aa59c6426..35cb7b1d73 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java @@ -16,13 +16,19 @@ package org.springframework.integration.config.xml; +import java.util.List; + 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.support.ManagedMap; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; /** * Parser for the <inbound-channel-adapter/> element. @@ -33,26 +39,79 @@ public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingIn @Override protected String parseSource(Element element, ParserContext parserContext) { - BeanComponentDefinition bcDef = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); - String sourceRef = null; - if (bcDef != null){ - sourceRef = bcDef.getBeanName(); - } else { - sourceRef = element.getAttribute("ref"); + BeanComponentDefinition innnerBeanDef = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + String sourceRef = element.getAttribute("ref"); + String expressionString = element.getAttribute("expression"); + if (innnerBeanDef != null) { + if (StringUtils.hasText(sourceRef)) { + parserContext.getReaderContext().error( + "inner bean and a 'ref' attribute are mutually exclusive options", element); + } + sourceRef = innnerBeanDef.getBeanName(); + } + else if (StringUtils.hasText(expressionString)) { + if (StringUtils.hasText(sourceRef)) { + parserContext.getReaderContext().error( + "the 'expression' and 'ref' attributes are mutually exclusive options", element); + } + sourceRef = this.parseExpression(expressionString, element, parserContext); } if (!StringUtils.hasText(sourceRef)) { - parserContext.getReaderContext().error("Either 'ref' attribute or inner-bean consumer definition is required.", element); + parserContext.getReaderContext().error("One of the following is required: " + + "'ref' attribute, 'expression' attribute, or an inner-bean definition.", element); } String methodName = element.getAttribute("method"); if (StringUtils.hasText(methodName)) { - BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition( + BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition( IntegrationNamespaceUtils.BASE_PACKAGE + ".endpoint.MethodInvokingMessageSource"); - invokerBuilder.addPropertyReference("object", sourceRef); - invokerBuilder.addPropertyValue("methodName", methodName); + sourceBuilder.addPropertyReference("object", sourceRef); + sourceBuilder.addPropertyValue("methodName", methodName); + this.parseHeaderExpressions(sourceBuilder, element, parserContext); sourceRef = BeanDefinitionReaderUtils.registerWithGeneratedName( - invokerBuilder.getBeanDefinition(), parserContext.getRegistry()); + sourceBuilder.getBeanDefinition(), parserContext.getRegistry()); } return sourceRef; } + private String parseExpression(String expressionString, Element element, ParserContext parserContext) { + BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.endpoint.ExpressionEvaluatingMessageSource"); + RootBeanDefinition expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expressionString); + sourceBuilder.addConstructorArgValue(expressionDef); + sourceBuilder.addConstructorArgValue(null); // TODO: add support for expectedType? + this.parseHeaderExpressions(sourceBuilder, element, parserContext); + return BeanDefinitionReaderUtils.registerWithGeneratedName(sourceBuilder.getBeanDefinition(), parserContext.getRegistry()); + } + + private void parseHeaderExpressions(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) { + List headerElements = DomUtils.getChildElementsByTagName(element, "header"); + if (!CollectionUtils.isEmpty(headerElements)) { + ManagedMap headerExpressions = new ManagedMap(); + for (Element headerElement : headerElements) { + String headerName = headerElement.getAttribute("name"); + String headerValue = headerElement.getAttribute("value"); + String headerExpression = headerElement.getAttribute("expression"); + boolean hasValue = StringUtils.hasText(headerValue); + boolean hasExpression = StringUtils.hasText(headerExpression); + if (!(hasValue ^ hasExpression)) { + parserContext.getReaderContext().error("exactly one of 'value' or 'expression' is required on a header sub-element", + parserContext.extractSource(headerElement)); + continue; + } + RootBeanDefinition expressionDef = null; + if (hasValue) { + expressionDef = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerValue); + } + else { + expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerExpression); + } + headerExpressions.put(headerName, expressionDef); + } + builder.addPropertyValue("headerExpressions", headerExpressions); + } + } + } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java deleted file mode 100644 index 76de916cb3..0000000000 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/ScheduledProducerParser.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2010 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.config.xml; - -import java.util.List; - -import org.w3c.dom.Element; - -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; -import org.springframework.beans.factory.support.ManagedMap; -import org.springframework.beans.factory.support.RootBeanDefinition; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; - -/** - * Parser for the <scheduled-producer> element. - * - * @author Mark Fisher - * @since 2.0 - */ -public class ScheduledProducerParser extends AbstractPollingInboundChannelAdapterParser { - - @Override - protected String parseSource(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.endpoint.ExpressionEvaluatingMessageSource"); - String payloadExpression = element.getAttribute("payload-expression"); - RootBeanDefinition expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); - expressionDef.getConstructorArgumentValues().addGenericArgumentValue(payloadExpression); - builder.addConstructorArgValue(expressionDef); - builder.addConstructorArgValue(null); // TODO: add support for expectedType? - this.parseHeaderExpressions(builder, element, parserContext); - return BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); - } - - private void parseHeaderExpressions(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) { - List headerElements = DomUtils.getChildElementsByTagName(element, "header"); - if (!CollectionUtils.isEmpty(headerElements)) { - ManagedMap headerExpressions = new ManagedMap(); - for (Element headerElement : headerElements) { - String headerName = headerElement.getAttribute("name"); - String headerValue = headerElement.getAttribute("value"); - String headerExpression = headerElement.getAttribute("expression"); - boolean hasValue = StringUtils.hasText(headerValue); - boolean hasExpression = StringUtils.hasText(headerExpression); - if (!(hasValue ^ hasExpression)) { - parserContext.getReaderContext().error("exactly one of 'value' or 'expression' is required on a header sub-element", - parserContext.extractSource(headerElement)); - continue; - } - RootBeanDefinition expressionDef = null; - if (hasValue) { - expressionDef = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); - expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerValue); - } - else { - expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); - expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerExpression); - } - headerExpressions.put(headerName, expressionDef); - } - builder.addPropertyValue("headerExpressions", headerExpressions); - } - } - -} diff --git a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd index 2e95e67a30..e86350c029 100644 --- a/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd +++ b/spring-integration-core/src/main/resources/org/springframework/integration/config/xml/spring-integration-2.0.xsd @@ -656,13 +656,30 @@ - + Defines a Channel Adapter that receives from a MessageSource and sends to a MessageChannel. + + + + + + + + + + + + + + + + + @@ -737,36 +754,37 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + SpEL expression to be evaluated for each triggered execution. + The result of the evaluation will be passed as the payload of + the Message that is sent to the MessageChannel. + + + + - - - - - + @@ -778,6 +796,22 @@ + + + + + + + + + + + + + + + + @@ -2409,86 +2443,6 @@ Name of the header whose value to use. - - - - Defines a component that evaluates an expression to generate a Message payload - (as well as optional - expression evaluation for headers). The resulting Message - is then sent to a MessageChannel. Each execution is driven - by a Trigger. - Exactly one of the trigger type attributes must be provided. The options are: - fixed-delay, fixed-rate, - cron, or trigger (reference). - - - - - - - - - - - Fixed delay trigger (in milliseconds). - - - - - Fixed rate trigger (in milliseconds). - - - - - Cron trigger. - - - - - - Reference to a Trigger instance. - - - - - - - - - - - - SpEL expression to be evaluated for each triggered execution. - The result of the evaluation will - be passed as the payload of - the Message that is sent to the MessageChannel. - - - - - - - MessageChannel to which this producer's output should be sent. - - - - - - - - - - - - Specify whether this producer should start automatically. - By default it will. Set this to 'false' - to require a manual start. - - - - - - diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests-context.xml similarity index 58% rename from spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml rename to spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests-context.xml index c024d187a8..41d3c2c6f7 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests-context.xml @@ -19,27 +19,27 @@ - + - + - + - + - + - + - +
- + - + - + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests.java similarity index 99% rename from spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java rename to spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests.java index 203f34fe5a..6d1e7b0acc 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/xml/ScheduledProducerParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/xml/InboundChannelAdapterExpressionTests.java @@ -42,7 +42,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) -public class ScheduledProducerParserTests { +public class InboundChannelAdapterExpressionTests { @Autowired private ApplicationContext context;