From 785d10263c7072c0f606e206db62629ca840a22f Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Sun, 13 Nov 2011 16:31:50 +0200 Subject: [PATCH] INT-1906 fix & refactor DefaultInboundChannelAdapterParser, plus some improvements --- ...> DefaultInboundChannelAdapterParser.java} | 60 +++++----- .../DefaultOutboundChannelAdapterParser.java | 105 ++++++++++++++++++ .../xml/IntegrationNamespaceHandler.java | 4 +- .../config/xml/IntegrationNamespaceUtils.java | 2 + ...dInvokingOutboundChannelAdapterParser.java | 77 ------------- .../ExpressionEvaluatingMessageHandler.java | 1 + .../util/BeanFactoryTypeConverter.java | 3 +- .../ChannelAdapterParserTests-context.xml | 86 +++++++------- .../config/ChannelAdapterParserTests.java | 43 ++++++- ...erInnerBeanWithExpression-fail-context.xml | 19 ++++ ...pressionEvaluatingMessageHandlerTests.java | 1 + 11 files changed, 248 insertions(+), 153 deletions(-) rename spring-integration-core/src/main/java/org/springframework/integration/config/xml/{MethodInvokingInboundChannelAdapterParser.java => DefaultInboundChannelAdapterParser.java} (74%) create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultOutboundChannelAdapterParser.java delete mode 100644 spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageHandler.java create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/config/InboundChannelAdapterInnerBeanWithExpression-fail-context.xml create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/message/ExpressionEvaluatingMessageHandlerTests.java 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/DefaultInboundChannelAdapterParser.java similarity index 74% rename from spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingInboundChannelAdapterParser.java rename to spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultInboundChannelAdapterParser.java index a1930ee0fd..450cdf31e6 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/DefaultInboundChannelAdapterParser.java @@ -18,6 +18,10 @@ package org.springframework.integration.config.xml; import java.util.List; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.config.ExpressionFactoryBean; +import org.springframework.integration.endpoint.ExpressionEvaluatingMessageSource; +import org.springframework.integration.endpoint.MethodInvokingMessageSource; import org.w3c.dom.Element; import org.springframework.beans.BeanMetadataElement; @@ -34,41 +38,49 @@ import org.springframework.util.xml.DomUtils; /** * Parser for the <inbound-channel-adapter/> element. - * + * * @author Mark Fisher + * @author Artem Bilan */ -public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { +public class DefaultInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { @Override protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) { BeanMetadataElement result = null; BeanComponentDefinition innnerBeanDef = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); - String sourceRef = element.getAttribute("ref"); - String methodName = element.getAttribute("method"); - 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); - } - if (StringUtils.hasText(methodName)) { + String sourceRef = element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE); + String methodName = element.getAttribute(IntegrationNamespaceUtils.METHOD_ATTRIBUTE); + String expressionString = element.getAttribute(IntegrationNamespaceUtils.EXPRESSION_ATTRIBUTE); + + boolean isInnerDef = innnerBeanDef != null; + boolean isRef = StringUtils.hasText(sourceRef); + boolean isExpression = StringUtils.hasText(expressionString); + boolean hasMethod = StringUtils.hasText(methodName); + + if (!(isInnerDef ^ (isRef ^ isExpression))) { + parserContext.getReaderContext().error( + "Exactly one of the 'ref', 'expression' or inner bean is required.", element); + } + + if (isInnerDef) { + if (hasMethod) { result = this.parseMethodInvokingSource(innnerBeanDef, methodName, element, parserContext); } else { result = innnerBeanDef; } } - else if (StringUtils.hasText(expressionString)) { - if (StringUtils.hasText(sourceRef)) { + else if (isExpression) { + if (hasMethod) { parserContext.getReaderContext().error( - "the 'expression' and 'ref' attributes are mutually exclusive options", element); + "The 'method' attribute can't be used with 'expression' attribute.", element); } String expressionBeanName = this.parseExpression(expressionString, element, parserContext); result = new RuntimeBeanReference(expressionBeanName); } - else if (StringUtils.hasText(sourceRef)) { - BeanMetadataElement sourceValue = new RuntimeBeanReference(sourceRef); - if (StringUtils.hasText(methodName)) { + else if (isRef) { + BeanMetadataElement sourceValue = new RuntimeBeanReference(sourceRef); + if (hasMethod) { result = this.parseMethodInvokingSource(sourceValue, methodName, element, parserContext); } else { @@ -83,8 +95,7 @@ public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingIn } private BeanMetadataElement parseMethodInvokingSource(BeanMetadataElement targetObject, String methodName, Element element, ParserContext parserContext) { - BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition( - IntegrationNamespaceUtils.BASE_PACKAGE + ".endpoint.MethodInvokingMessageSource"); + BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingMessageSource.class); sourceBuilder.addPropertyValue("object", targetObject); sourceBuilder.addPropertyValue("methodName", methodName); this.parseHeaderExpressions(sourceBuilder, element, parserContext); @@ -94,12 +105,11 @@ public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingIn } 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"); + BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionEvaluatingMessageSource.class); + RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class); expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expressionString); sourceBuilder.addConstructorArgValue(expressionDef); - sourceBuilder.addConstructorArgValue(null); // TODO: add support for expectedType? + sourceBuilder.addConstructorArgValue(null); this.parseHeaderExpressions(sourceBuilder, element, parserContext); return BeanDefinitionReaderUtils.registerWithGeneratedName(sourceBuilder.getBeanDefinition(), parserContext.getRegistry()); } @@ -121,11 +131,11 @@ public class MethodInvokingInboundChannelAdapterParser extends AbstractPollingIn } RootBeanDefinition expressionDef = null; if (hasValue) { - expressionDef = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); + expressionDef = new RootBeanDefinition(LiteralExpression.class); expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerValue); } else { - expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); + expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class); expressionDef.getConstructorArgumentValues().addGenericArgumentValue(headerExpression); } headerExpressions.put(headerName, expressionDef); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultOutboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultOutboundChannelAdapterParser.java new file mode 100644 index 0000000000..39adc69cb1 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/DefaultOutboundChannelAdapterParser.java @@ -0,0 +1,105 @@ +/* + * Copyright 2002-2009 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 org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.integration.config.ExpressionFactoryBean; +import org.springframework.integration.handler.ExpressionEvaluatingMessageHandler; +import org.springframework.integration.handler.MethodInvokingMessageHandler; +import org.w3c.dom.Element; + +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; + +/** + * Parser for the <outbound-channel-adapter/> element. + * + * @author Mark Fisher + * @author Oleg Zhurakousky + * @author Artem Bilan + */ +public class DefaultOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { + + protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) { + BeanComponentDefinition innerConsumerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); + String consumerRef = element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE); + String methodName = element.getAttribute(IntegrationNamespaceUtils.METHOD_ATTRIBUTE); + String consumerExpressionString = element.getAttribute(IntegrationNamespaceUtils.EXPRESSION_ATTRIBUTE); + + boolean isInnerConsumer = innerConsumerDefinition != null; + boolean isRef = StringUtils.hasText(consumerRef); + boolean isExpression = StringUtils.hasText(consumerExpressionString); + boolean hasMethod = StringUtils.hasText(methodName); + + if (!(isInnerConsumer ^ (isRef ^ isExpression))) { + parserContext.getReaderContext().error( + "Exactly one of the 'ref', 'expression' or inner bean is required.", element); + } + + if (hasMethod & isExpression) { + parserContext.getReaderContext().error( + "The 'method' attribute can't be used with 'expression' attribute.", element); + } + + + if (hasMethod | isExpression) { + BeanDefinitionBuilder consumerBuilder = null; + + if (hasMethod) { + consumerBuilder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingMessageHandler.class); + if (isRef) { + consumerBuilder.addConstructorArgReference(consumerRef); + } + else { + consumerBuilder.addConstructorArgValue(innerConsumerDefinition); + } + consumerBuilder.addConstructorArgValue(methodName); + } + else { + consumerBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionEvaluatingMessageHandler.class); + RootBeanDefinition expressionDef = new RootBeanDefinition(ExpressionFactoryBean.class); + expressionDef.getConstructorArgumentValues().addGenericArgumentValue(consumerExpressionString); + consumerBuilder.addConstructorArgValue(expressionDef); + } + + consumerBuilder.addPropertyValue("componentType", "outbound-channel-adapter"); + + String order = element.getAttribute(IntegrationNamespaceUtils.ORDER); + if (StringUtils.hasText(order)) { + consumerBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, order); + } + + consumerRef = BeanDefinitionReaderUtils.registerWithGeneratedName(consumerBuilder.getBeanDefinition(), parserContext.getRegistry()); + } + else if (isInnerConsumer) { + consumerRef = innerConsumerDefinition.getBeanName(); + } + + Assert.hasText(consumerRef, "Can not determine consumer for 'outbound-channel-adapter'"); + return consumerRef; + } + + @Override + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + throw new UnsupportedOperationException(); + } +} 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 ce084278c6..de6ff7f1ad 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 @@ -52,9 +52,9 @@ public class IntegrationNamespaceHandler extends AbstractIntegrationNamespaceHan registerBeanDefinitionParser("payload-deserializing-transformer", new PayloadDeserializingTransformerParser()); registerBeanDefinitionParser("claim-check-in", new ClaimCheckInParser()); registerBeanDefinitionParser("claim-check-out", new ClaimCheckOutParser()); - registerBeanDefinitionParser("inbound-channel-adapter", new MethodInvokingInboundChannelAdapterParser()); + registerBeanDefinitionParser("inbound-channel-adapter", new DefaultInboundChannelAdapterParser()); registerBeanDefinitionParser("resource-inbound-channel-adapter", new ResourceInboundChannelAdapterParser()); - registerBeanDefinitionParser("outbound-channel-adapter", new MethodInvokingOutboundChannelAdapterParser()); + registerBeanDefinitionParser("outbound-channel-adapter", new DefaultOutboundChannelAdapterParser()); registerBeanDefinitionParser("logging-channel-adapter", new LoggingChannelAdapterParser()); registerBeanDefinitionParser("gateway", new GatewayParser()); registerBeanDefinitionParser("delayer", new DelayerParser()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java index 17611c92aa..459d26dcc4 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceUtils.java @@ -36,6 +36,7 @@ import org.w3c.dom.Element; * @author Alex Peters * @author Oleg Zhurakousky * @author Gary Russell + * @author Artem Bilan */ public abstract class IntegrationNamespaceUtils { @@ -43,6 +44,7 @@ public abstract class IntegrationNamespaceUtils { static final String REF_ATTRIBUTE = "ref"; static final String METHOD_ATTRIBUTE = "method"; static final String ORDER = "order"; + static final String EXPRESSION_ATTRIBUTE = "expression"; /** * Configures the provided bean definition builder with a property value corresponding to the attribute whose name diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java deleted file mode 100644 index ab35b765d3..0000000000 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/MethodInvokingOutboundChannelAdapterParser.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2009 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 org.w3c.dom.Element; - -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; - -/** - * Parser for the <outbound-channel-adapter/> element. - * - * @author Mark Fisher - * @author Oleg Zhurakousky - */ -public class MethodInvokingOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { - - protected String parseAndRegisterConsumer(Element element, ParserContext parserContext) { - 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()); - } - Assert.hasText(consumerRef, "Can not determine consumer for 'outbound-channel-adapter'"); - return consumerRef; - } - - @Override - protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { - BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition( - IntegrationNamespaceUtils.BASE_PACKAGE + ".handler.MethodInvokingMessageHandler"); - - invokerBuilder.addPropertyValue("componentType", "outbound-channel-adapter"); - BeanComponentDefinition innerHandlerDefinition = - IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); - if (innerHandlerDefinition == null){ - Assert.hasText(element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE), - "You must provide 'ref' attribute or register inner bean for " + - "Outbound Channel consumer."); - invokerBuilder.addConstructorArgReference(element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE)); - } else { - invokerBuilder.addConstructorArgValue(innerHandlerDefinition); - } - invokerBuilder.addConstructorArgValue(element.getAttribute(IntegrationNamespaceUtils.METHOD_ATTRIBUTE)); - String order = element.getAttribute(IntegrationNamespaceUtils.ORDER); - if (StringUtils.hasText(order)) { - invokerBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, order); - } - return invokerBuilder.getBeanDefinition(); - } -} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageHandler.java new file mode 100644 index 0000000000..ed737be749 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/ExpressionEvaluatingMessageHandler.java @@ -0,0 +1 @@ +/* * Copyright 2002-2011 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.handler; import org.springframework.expression.Expression; import org.springframework.integration.Message; /** * A {@link org.springframework.integration.core.MessageHandler} that evaluates provided {@link Expression} * with void return. * * @author Artem Bilan * @see MethodInvokingMessageHandler * @since 2.1 */ public class ExpressionEvaluatingMessageHandler extends AbstractMessageHandler { private volatile ExpressionEvaluatingMessageProcessor processor; private volatile String componentType; public ExpressionEvaluatingMessageHandler(Expression expression) { processor = new ExpressionEvaluatingMessageProcessor(expression, Void.class); } @Override protected void onInit() throws Exception { processor.setBeanFactory(getBeanFactory()); } public void setComponentType(String componentType) { this.componentType = componentType; } @Override public String getComponentType() { return this.componentType; } @Override protected void handleMessageInternal(Message message) throws Exception { processor.processMessage(message); } } \ No newline at end of file diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/BeanFactoryTypeConverter.java b/spring-integration-core/src/main/java/org/springframework/integration/util/BeanFactoryTypeConverter.java index 59f08cdcb0..84bcd6af66 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/BeanFactoryTypeConverter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/BeanFactoryTypeConverter.java @@ -94,7 +94,8 @@ public class BeanFactoryTypeConverter implements TypeConverter, BeanFactoryAware } public Object convertValue(Object value, TypeDescriptor sourceType, TypeDescriptor targetType) { - if (targetType.getType() == Void.class || targetType.getType() == Void.TYPE) { + // TODO maybe tentative decision... Echoes with org.springframework.expression.common.ExpressionUtils.convertTypedValue() + if ((targetType.getType() == Void.class || targetType.getType() == Void.TYPE) && value == null) { return null; } if (conversionService.canConvert(sourceType, targetType)) { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-context.xml index 2713b946da..64f907f504 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-context.xml +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests-context.xml @@ -1,46 +1,48 @@ - + + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/integration + http://www.springframework.org/schema/integration/spring-integration.xsd"> - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - - + + + - + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java index 7b55192c93..6e8746fc2a 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelAdapterParserTests.java @@ -23,13 +23,16 @@ import static org.junit.Assert.assertTrue; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageHandler; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; @@ -41,6 +44,7 @@ import org.springframework.integration.test.util.TestUtils; /** * @author Mark Fisher * @author Oleg Zhurakousky + * @author Artem Bilan */ public class ChannelAdapterParserTests { @@ -134,6 +138,27 @@ public class ChannelAdapterParserTests { assertEquals("consumer test", testBean.getMessage()); } + @Test + /** + * @since 2.1 + */ + public void expressionConsumer() { + String beanName = "expressionConsumer"; + Object channel = this.applicationContext.getBean(beanName); + assertTrue(channel instanceof DirectChannel); + BeanFactoryChannelResolver channelResolver = new BeanFactoryChannelResolver(this.applicationContext); + assertNotNull(channelResolver.resolveChannelName(beanName)); + Object adapter = this.applicationContext.getBean(beanName + ".adapter"); + assertNotNull(adapter); + assertTrue(adapter instanceof EventDrivenConsumer); + TestBean testBean = (TestBean) this.applicationContext.getBean("testBean"); + assertNull(testBean.getMessage()); + Message message = new GenericMessage("consumer test expression"); + assertTrue(((MessageChannel) channel).send(message)); + assertNotNull(testBean.getMessage()); + assertEquals("consumer test expression", testBean.getMessage()); + } + @Test public void methodInvokingSource() { String beanName = "methodInvokingSource"; @@ -221,19 +246,24 @@ public class ChannelAdapterParserTests { BeanFactoryChannelResolver channelResolver = new BeanFactoryChannelResolver(this.applicationContext); channelResolver.resolveChannelName("methodInvokingSource"); } - + @Test - public void methodInvokingSourceWithSendTimeout() throws Exception{ + public void methodInvokingSourceWithSendTimeout() throws Exception { String beanName = "methodInvokingSourceWithTimeout"; - - SourcePollingChannelAdapter adapter = - this.applicationContext.getBean(beanName, SourcePollingChannelAdapter.class); + + SourcePollingChannelAdapter adapter = + this.applicationContext.getBean(beanName, SourcePollingChannelAdapter.class); assertNotNull(adapter); long sendTimeout = TestUtils.getPropertyValue(adapter, "messagingTemplate.sendTimeout", Long.class); assertEquals(999, sendTimeout); } - public static class SampleBean{ + @Test(expected = BeanDefinitionParsingException.class) + public void innerBeanAndExpressionFail() throws Exception { + new ClassPathXmlApplicationContext("InboundChannelAdapterInnerBeanWithExpression-fail-context.xml", this.getClass()); + } + + public static class SampleBean { private String message = "hello"; String getMessage() { @@ -241,3 +271,4 @@ public class ChannelAdapterParserTests { } } } + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/InboundChannelAdapterInnerBeanWithExpression-fail-context.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/InboundChannelAdapterInnerBeanWithExpression-fail-context.xml new file mode 100644 index 0000000000..745a19f9e4 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/InboundChannelAdapterInnerBeanWithExpression-fail-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/message/ExpressionEvaluatingMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/message/ExpressionEvaluatingMessageHandlerTests.java new file mode 100644 index 0000000000..7b6b098251 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/message/ExpressionEvaluatingMessageHandlerTests.java @@ -0,0 +1 @@ +/* * Copyright 2002-2011 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.message; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.Message; import org.springframework.integration.MessagingException; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.handler.ExpressionEvaluatingMessageHandler; import java.util.HashMap; import static org.junit.Assert.assertEquals; /** * @author Artem Bilan * @since 2.1 */ public class ExpressionEvaluatingMessageHandlerTests { private ExpressionParser parser; @Before public void setup() { parser = new SpelExpressionParser(); } @Test public void validExpression() { Expression expression = parser.parseExpression("T(System).out.println(payload)"); MessageHandler handler = new ExpressionEvaluatingMessageHandler(expression); handler.handleMessage(new GenericMessage("test")); } @Test public void validExpressionWithNoArgs() { Expression expression = parser.parseExpression("T(System).out.println()"); MessageHandler handler = new ExpressionEvaluatingMessageHandler(expression); handler.handleMessage(new GenericMessage("test")); } @Test public void validExpressionWithSomeArgs() { Expression expression = parser.parseExpression("T(System).out.write(payload.bytes, 0, headers.offset)"); MessageHandler handler = new ExpressionEvaluatingMessageHandler(expression); HashMap headers = new HashMap(); headers.put("offset", 4); handler.handleMessage(new GenericMessage("testtest", headers)); } @Test(expected = MessagingException.class) public void expressionWithReturnValue() { Message message = new GenericMessage(.1f); try { Expression expression = parser.parseExpression("T(System).out.printf('$%4.2f', payload)"); MessageHandler handler = new ExpressionEvaluatingMessageHandler(expression); handler.handleMessage(message); } catch (MessagingException e) { assertEquals(e.getFailedMessage(), message); throw e; } } } \ No newline at end of file