From ccffab2d177c0ed9e9e3fca0a30a93a956cb166e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 29 Apr 2011 11:38:22 -0400 Subject: [PATCH] INT-1881 added support for nesting processing beans in the 'header' element of header-enricher (e.g., bean, script etc.) --- .../xml/HeaderEnricherParserSupport.java | 45 ++++++++++++-- .../transformer/HeaderEnricher.java | 11 ++++ .../config/xml/spring-integration-2.0.xsd | 5 +- .../groovy/config/GroovyScriptParser.java | 4 ++ .../GroovyHeaderEnricherTests-context.xml | 39 ++++++++++++ .../config/GroovyHeaderEnricherTests.groovy | 1 + .../config/GroovyHeaderEnricherTests.java | 62 +++++++++++++++++++ 7 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests-context.xml create mode 100644 spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.groovy create mode 100644 spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/HeaderEnricherParserSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/HeaderEnricherParserSupport.java index 9461cd4f31..11a6d097ff 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/HeaderEnricherParserSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/HeaderEnricherParserSupport.java @@ -17,12 +17,14 @@ package org.springframework.integration.config.xml; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; @@ -35,6 +37,7 @@ import org.springframework.util.xml.DomUtils; * Base support class for 'header-enricher' parsers. * * @author Mark Fisher + * @author Oleg Zhurakousky * @since 2.0 */ public abstract class HeaderEnricherParserSupport extends AbstractTransformerParser { @@ -113,18 +116,36 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar String ref = headerElement.getAttribute("ref"); String method = headerElement.getAttribute("method"); String expression = headerElement.getAttribute("expression"); - Element expressionElement = DomUtils.getChildElementByTagName(headerElement, "expression"); - if (StringUtils.hasText(expression) && expressionElement != null) { - parserContext.getReaderContext().error("The 'expression' attribute and sub-element are mutually exclusive", element); - return; + + List subElements = DomUtils.getChildElements(headerElement); + + BeanDefinition innerComponentDefinition = null; + Element expressionElement = null; + if (subElements != null && subElements.size() == 1) { + Element beanElement = subElements.get(0); + if ("expression".equals(beanElement.getNodeName())){ + expressionElement = beanElement; + if (StringUtils.hasText(expression) && expressionElement != null) { + parserContext.getReaderContext().error("The 'expression' attribute and sub-element are mutually exclusive", element); + return; + } + } + else if ("bean".equals(beanElement.getNodeName())){ + innerComponentDefinition = parserContext.getDelegate().parseBeanDefinitionElement(beanElement).getBeanDefinition(); + } + else { + innerComponentDefinition = parserContext.getDelegate().parseCustomElement(beanElement); + } } boolean isValue = StringUtils.hasText(value); boolean isRef = StringUtils.hasText(ref); boolean hasMethod = StringUtils.hasText(method); boolean isExpression = StringUtils.hasText(expression) || expressionElement != null; - if (!(isValue ^ (isRef ^ isExpression))) { + boolean isCustomBean = innerComponentDefinition != null; + + if (!(isValue ^ (isRef ^ (isExpression ^ isCustomBean)))) { parserContext.getReaderContext().error( - "Exactly one of the 'ref', 'value', or 'expression' attributes is required.", element); + "Exactly one of the 'ref', 'value', 'expression' or inner bean is required.", element); } BeanDefinitionBuilder valueProcessorBuilder = null; if (isValue) { @@ -157,6 +178,18 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar } valueProcessorBuilder.addConstructorArgValue(headerType); } + else if (isCustomBean){ + valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition( + IntegrationNamespaceUtils.BASE_PACKAGE + ".transformer.HeaderEnricher$MethodInvokingHeaderValueMessageProcessor"); + valueProcessorBuilder.addConstructorArgValue(innerComponentDefinition); + if (hasMethod){ + valueProcessorBuilder.addConstructorArgValue(method); + } + else { + valueProcessorBuilder.addConstructorArgValue(null); + } + headers.put(headerName, valueProcessorBuilder.getBeanDefinition()); + } else { if (StringUtils.hasText(headerElement.getAttribute("type"))) { parserContext.getReaderContext().error( diff --git a/spring-integration-core/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java b/spring-integration-core/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java index 5945b400af..2f8c0d4f67 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java @@ -59,6 +59,17 @@ public class HeaderEnricher implements Transformer { public HeaderEnricher() { this(null); } + +// public HeaderEnricher(final MessageProcessor messageProcessor) { +// HeaderValueMessageProcessor hvProcessor = new AbstractHeaderValueMessageProcessor() { +// +// public Object processMessage(Message message) { +// // TODO Auto-generated method stub +// return messageProcessor.processMessage(message); +// } +// }; +// //this(hvProcessor); +// } /** * Create a HeaderEnricher with the given map of headers. 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 d7fb7a64b8..6974593944 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 @@ -1557,9 +1557,10 @@ endpoint itself is a Polling Consumer for a channel with a queue. - + + - + diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java index 3f6ad0dba8..2d65687252 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java @@ -49,6 +49,10 @@ public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser { protected String getBeanClassName(Element element) { return "org.springframework.integration.groovy.GroovyScriptExecutingMessageProcessor"; } + + protected boolean shouldGenerateIdAsFallback() { + return true; + } @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests-context.xml b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests-context.xml new file mode 100644 index 0000000000..586dbbfe96 --- /dev/null +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests-context.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.groovy b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.groovy new file mode 100644 index 0000000000..9c94dba346 --- /dev/null +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.groovy @@ -0,0 +1 @@ +"groovy" \ No newline at end of file diff --git a/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.java b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.java new file mode 100644 index 0000000000..fa2682c31d --- /dev/null +++ b/spring-integration-groovy/src/test/java/org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.java @@ -0,0 +1,62 @@ +/* + * 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.groovy.config; + +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.MessageChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.message.GenericMessage; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class GroovyHeaderEnricherTests { + + @Autowired + private MessageChannel inputA; + + @Autowired + private QueueChannel outputA; + + @Autowired + private MessageChannel inputB; + + @Autowired + private QueueChannel outputB; + + @Test + public void referencedScript() throws Exception{ + inputA.send(new GenericMessage("Hello")); + assertEquals("groovy", outputA.receive(1000).getHeaders().get("TEST_HEADER")); + } + + @Test + public void inlineScript() throws Exception{ + inputB.send(new GenericMessage("Hello")); + assertEquals("groovy", outputB.receive(1000).getHeaders().get("TEST_HEADER")); + } +}