diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java index 51a881e61e..227e412bac 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/IntegrationNamespaceHandler.java @@ -105,6 +105,7 @@ public class IntegrationNamespaceHandler implements NamespaceHandler { registerBeanDefinitionParser("splitter", new SplitterParser()); registerBeanDefinitionParser("aggregator", new AggregatorParser()); registerBeanDefinitionParser("resequencer", new ResequencerParser()); + registerBeanDefinitionParser("header-enricher", new StandardHeaderEnricherParser()); registerBeanDefinitionParser("inbound-channel-adapter", new MethodInvokingInboundChannelAdapterParser()); registerBeanDefinitionParser("outbound-channel-adapter", new MethodInvokingOutboundChannelAdapterParser()); registerBeanDefinitionParser("gateway", new GatewayParser()); diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SimpleHeaderEnricherParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SimpleHeaderEnricherParser.java index d07fce0bd0..c70abf4193 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SimpleHeaderEnricherParser.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/SimpleHeaderEnricherParser.java @@ -84,20 +84,18 @@ public class SimpleHeaderEnricherParser extends AbstractTransformerParser { Node node = attributes.item(i); String name = node.getNodeName(); if (this.isEligibleHeaderName(name)) { - if (this.referenceAttributes.contains(name)) { - headers.put(name, new RuntimeBeanReference(node.getNodeValue())); - } - else { - headers.put(name, node.getNodeValue()); + Object value = (this.referenceAttributes.contains(name)) + ? new RuntimeBeanReference(node.getNodeValue()) + : node.getNodeValue(); + if (this.prefix != null) { + name = this.prefix + name; } + headers.put(name, value); } } this.postProcessHeaders(element, headers); builder.addConstructorArgValue(headers); builder.addPropertyValue("overwrite", this.shouldOverwrite(element)); - if (this.prefix != null) { - builder.addPropertyValue("prefix", this.prefix); - } } /** diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/StandardHeaderEnricherParser.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/StandardHeaderEnricherParser.java new file mode 100644 index 0000000000..62d42b4266 --- /dev/null +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/StandardHeaderEnricherParser.java @@ -0,0 +1,74 @@ +/* + * Copyright 2002-2008 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.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.ManagedMap; +import org.springframework.integration.core.MessageHeaders; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * Parser for the <header-enricher> element within the core integration + * namespace. This is used for setting the standard, out-of-the-box + * configurable {@link MessageHeaders}, such as 'reply-channel', 'priority', + * and 'correlation-id'. It will also accept custom header values (or bean + * references) if provided as 'header' sub-elements. + * + * @author Mark Fisher + */ +public class StandardHeaderEnricherParser extends SimpleHeaderEnricherParser { + + private static final String[] REFERENCE_ATTRIBUTES = new String[] { + "reply-channel", "error-channel" + }; + + + public StandardHeaderEnricherParser() { + super(MessageHeaders.PREFIX, REFERENCE_ATTRIBUTES); + } + + + @Override + @SuppressWarnings("unchecked") + protected void postProcessHeaders(Element element, ManagedMap headers) { + NodeList childNodes = element.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("header")) { + Element headerElement = (Element) node; + String name = headerElement.getAttribute("name"); + String value = headerElement.getAttribute("value"); + String ref = headerElement.getAttribute("ref"); + boolean isValue = StringUtils.hasText(value); + boolean isRef = StringUtils.hasText(ref); + Assert.isTrue(isValue ^ isRef, "Exactly one of the 'value' or 'ref' attributes is required."); + if (isValue) { + headers.put(name, value); + } + else { + headers.put(name, new RuntimeBeanReference(ref)); + } + } + } + } + +} diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd index ad7dbc6e8b..0225dc0862 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/xml/spring-integration-1.0.xsd @@ -266,6 +266,14 @@ + + + + + + + + @@ -387,6 +395,48 @@ + + + + Defines a HeaderEnricher endpoint for values defined in the MessageHeaders. + + + + + + + + + + + + + + + + + + Defines a Message Header value or ref. + + + + + + + + + + + Provides the names of the standard configurable MessageHeaders. + + + + + + + + + diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java b/org.springframework.integration/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java index 5df8c04721..de36f5107e 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/transformer/HeaderEnricher.java @@ -22,8 +22,8 @@ import org.springframework.util.Assert; /** * A Transformer that adds statically configured header values to a Message. - * Accepts an optional 'prefix' String and a boolean that specifies whether - * values should be overwritten. By default, any existing header values for + * Accepts the boolean 'overwrite' property that specifies whether values + * should be overwritten. By default, any existing header values for * a given key, will not be replaced. * * @author Mark Fisher @@ -34,8 +34,6 @@ public class HeaderEnricher extends AbstractHeaderTransformer { private volatile boolean overwrite; - private volatile String prefix; - /** * Create a HeaderEnricher with the given map of headers. @@ -50,17 +48,10 @@ public class HeaderEnricher extends AbstractHeaderTransformer { this.overwrite = overwrite; } - public void setPrefix(String prefix) { - this.prefix = prefix; - } - @Override protected final void transformHeaders(Map headers) { for (Map.Entry entry : this.headersToAdd.entrySet()) { String key = entry.getKey(); - if (this.prefix != null) { - key = this.prefix + key; - } if (this.overwrite || headers.get(key) == null) { headers.put(key, entry.getValue()); } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests-context.xml b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests-context.xml index a3a45e9579..880aa84bd7 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests-context.xml +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests-context.xml @@ -7,17 +7,33 @@ http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-1.0.xsd"> - + - + + + + + + + +
+
+ + + + + + + + diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests.java index 633dde9bd1..42546fe8e3 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/config/ChainParserTests.java @@ -38,19 +38,27 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests; public class ChainParserTests extends AbstractJUnit4SpringContextTests { @Autowired - @Qualifier("input") - private MessageChannel inputChannel; + @Qualifier("filterInput") + private MessageChannel filterInput; + + @Autowired + @Qualifier("headerEnricherInput") + private MessageChannel headerEnricherInput; @Autowired @Qualifier("output") - private PollableChannel outputChannel; + private PollableChannel output; + + @Autowired + @Qualifier("replyOutput") + private PollableChannel replyOutput; @Test - public void testChainWithAcceptingFilter() { + public void chainWithAcceptingFilter() { Message message = MessageBuilder.withPayload("test").build(); - this.inputChannel.send(message); - Message reply = this.outputChannel.receive(0); + this.filterInput.send(message); + Message reply = this.output.receive(0); assertNotNull(reply); assertEquals("foo", reply.getPayload()); } @@ -58,9 +66,21 @@ public class ChainParserTests extends AbstractJUnit4SpringContextTests { @Test public void chainWithRejectingFilter() { Message message = MessageBuilder.withPayload(123).build(); - this.inputChannel.send(message); - Message reply = this.outputChannel.receive(0); + this.filterInput.send(message); + Message reply = this.output.receive(0); assertNull(reply); } + @Test + public void chainWithHeaderEnricher() { + Message message = MessageBuilder.withPayload(123).build(); + this.headerEnricherInput.send(message); + Message reply = this.replyOutput.receive(0); + assertNotNull(reply); + assertEquals("foo", reply.getPayload()); + assertEquals("ABC", reply.getHeaders().getCorrelationId()); + assertEquals("XYZ", reply.getHeaders().get("testValue")); + assertEquals(123, reply.getHeaders().get("testRef")); + } + }