INT-1881 added support for nesting processing beans in the 'header' element of header-enricher (e.g., bean, script etc.)
This commit is contained in:
@@ -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<Element> 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(
|
||||
|
||||
@@ -59,6 +59,17 @@ public class HeaderEnricher implements Transformer {
|
||||
public HeaderEnricher() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
// public HeaderEnricher(final MessageProcessor<?> messageProcessor) {
|
||||
// HeaderValueMessageProcessor<?> hvProcessor = new AbstractHeaderValueMessageProcessor<Object>() {
|
||||
//
|
||||
// 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.
|
||||
|
||||
@@ -1557,9 +1557,10 @@ endpoint itself is a Polling Consumer for a channel with a queue.
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="referenceHeaderType">
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:choice minOccurs="0" maxOccurs="1">
|
||||
<xsd:any processContents="strict" namespace="##other"/>
|
||||
<xsd:element name="expression" type="innerExpressionType" />
|
||||
</xsd:sequence>
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="value" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-groovy="http://www.springframework.org/schema/integration/groovy"
|
||||
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
|
||||
http://www.springframework.org/schema/integration/groovy http://www.springframework.org/schema/integration/groovy/spring-integration-groovy-2.0.xsd">
|
||||
|
||||
<int:channel id="inputA"/>
|
||||
|
||||
<int:header-enricher input-channel="inputA" output-channel="outputA">
|
||||
<int:header name="TEST_HEADER">
|
||||
<int-groovy:script location="org/springframework/integration/groovy/config/GroovyHeaderEnricherTests.groovy"/>
|
||||
</int:header>
|
||||
</int:header-enricher>
|
||||
|
||||
<int:channel id="outputA">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
|
||||
<int:channel id="inputB"/>
|
||||
|
||||
<int:header-enricher input-channel="inputB" output-channel="outputB">
|
||||
<int:header name="TEST_HEADER">
|
||||
<int-groovy:script>
|
||||
<![CDATA[
|
||||
return "groovy"
|
||||
]]>
|
||||
</int-groovy:script>
|
||||
</int:header>
|
||||
</int:header-enricher>
|
||||
|
||||
<int:channel id="outputB">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1 @@
|
||||
"groovy"
|
||||
@@ -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<String>("Hello"));
|
||||
assertEquals("groovy", outputA.receive(1000).getHeaders().get("TEST_HEADER"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inlineScript() throws Exception{
|
||||
inputB.send(new GenericMessage<String>("Hello"));
|
||||
assertEquals("groovy", outputB.receive(1000).getHeaders().get("TEST_HEADER"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user