diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java index a497ab74d2..dcacff0373 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java @@ -364,14 +364,7 @@ public class MethodInvokingMessageProcessor extends AbstractMessageProcessor { } else if (annotationType.equals(Header.class)) { Header headerAnnotation = (Header) mappingAnnotation; - String headerName = this.determineHeaderName(headerAnnotation, new MethodParameter(method, i)); - String headerExpression = "headers." + headerName; - if (headerAnnotation.required()) { - sb.append(headerExpression); - } - else { - sb.append("headers[" + headerName + "] != null ? " + headerExpression + " : null"); - } + sb.append(this.determineHeaderExpression(headerAnnotation, new MethodParameter(method, i))); } } else if (Message.class.isAssignableFrom(parameterType)) { @@ -428,13 +421,35 @@ public class MethodInvokingMessageProcessor extends AbstractMessageProcessor { return match; } - private String determineHeaderName(Header headerAnnotation, MethodParameter methodParameter) { + private String determineHeaderExpression(Header headerAnnotation, MethodParameter methodParameter) { methodParameter.initParameterNameDiscovery(PARAMETER_NAME_DISCOVERER); + String headerName = null; + String relativeExpression = ""; String valueAttribute = headerAnnotation.value(); - String headerName = StringUtils.hasText(valueAttribute) ? valueAttribute : methodParameter.getParameterName(); + if (!StringUtils.hasText(valueAttribute)) { + headerName = methodParameter.getParameterName(); + } + else if (valueAttribute.indexOf('.') != -1) { + String tokens[] = valueAttribute.split("\\.", 2); + headerName = tokens[0]; + if (StringUtils.hasText(tokens[1])) { + relativeExpression = "." + tokens[1]; + } + } + else { + headerName = valueAttribute; + } Assert.notNull(headerName, "Cannot determine header name. Possible reasons: -debug is " + "disabled or header name is not explicitly provided via @Header annotation."); - return headerName; + if (headerName.startsWith("$")) { + // rely on access to getSomeValue for $someValue + headerName = headerName.substring(1); + } + String headerExpression = "headers." + headerName + relativeExpression; + if (headerAnnotation.required()) { + return headerExpression; + } + return "headers['" + headerName + "'] != null ? " + headerExpression + " : null"; } private synchronized void setExclusiveTargetParameterType(Class targetParameterType) { @@ -443,21 +458,26 @@ public class MethodInvokingMessageProcessor extends AbstractMessageProcessor { this.targetParameterType = targetParameterType; } } + + /** * @author Oleg Zhurakousky * @since 2.0 */ - private class UniqueMethodFilter implements MethodFilter { + private static class UniqueMethodFilter implements MethodFilter { + private List uniqueMethods = new ArrayList(); - - public UniqueMethodFilter(Class targetClass){ + + public UniqueMethodFilter(Class targetClass) { ArrayList allMethods = new ArrayList(Arrays.asList(targetClass.getMethods())); for (Method method : allMethods) { uniqueMethods.add(org.springframework.util.ClassUtils.getMostSpecificMethod(method, targetClass)); } } + public boolean matches(Method method) { return uniqueMethods.contains(method); } } + } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/handler/HeaderAnnotationTransformerTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/handler/HeaderAnnotationTransformerTests.java new file mode 100644 index 0000000000..29c7a00838 --- /dev/null +++ b/org.springframework.integration/src/test/java/org/springframework/integration/handler/HeaderAnnotationTransformerTests.java @@ -0,0 +1,119 @@ +/* + * 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.handler; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Test; + +import org.springframework.integration.annotation.Header; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.core.Message; +import org.springframework.integration.core.MessageHeaders; +import org.springframework.integration.message.MessageBuilder; +import org.springframework.integration.transformer.MessageTransformingHandler; +import org.springframework.integration.transformer.MethodInvokingTransformer; + +/** + * @author Mark Fisher + * @since 2.0 + */ +public class HeaderAnnotationTransformerTests { + + @Test // INT-1082 + public void headerAnnotationWithPrefixedHeader() { + Object target = new TestTransformer(); + MethodInvokingTransformer transformer = new MethodInvokingTransformer(target, "appendCorrelationId"); + MessageTransformingHandler handler = new MessageTransformingHandler(transformer); + handler.afterPropertiesSet(); + QueueChannel outputChannel = new QueueChannel(); + handler.setOutputChannel(outputChannel); + handler.handleMessage(MessageBuilder.withPayload("test").setCorrelationId("abc").build()); + Message result = outputChannel.receive(0); + assertNotNull(result); + assertEquals("testabc", result.getPayload()); + assertEquals("abc", result.getHeaders().getCorrelationId()); + } + + @Test // INT-1082 + public void headerAnnotationWithPrefixedHeaderAndRelativeExpression() { + Object target = new TestTransformer(); + MethodInvokingTransformer transformer = new MethodInvokingTransformer(target, "evalCorrelationId"); + MessageTransformingHandler handler = new MessageTransformingHandler(transformer); + handler.afterPropertiesSet(); + QueueChannel outputChannel = new QueueChannel(); + handler.setOutputChannel(outputChannel); + handler.handleMessage(MessageBuilder.withPayload("test").setCorrelationId("abc").build()); + Message result = outputChannel.receive(0); + assertNotNull(result); + assertEquals("ABC", result.getPayload()); + assertEquals("abc", result.getHeaders().getCorrelationId()); + } + + @Test + public void headerAnnotationWithUnprefixedHeader() { + Object target = new TestTransformer(); + MethodInvokingTransformer transformer = new MethodInvokingTransformer(target, "appendFoo"); + MessageTransformingHandler handler = new MessageTransformingHandler(transformer); + handler.afterPropertiesSet(); + QueueChannel outputChannel = new QueueChannel(); + handler.setOutputChannel(outputChannel); + handler.handleMessage(MessageBuilder.withPayload("test").setHeader("foo", "bar").build()); + Message result = outputChannel.receive(0); + assertNotNull(result); + assertEquals("testbar", result.getPayload()); + assertEquals("bar", result.getHeaders().get("foo")); + } + + @Test + public void headerAnnotationWithUnprefixedHeaderAndRelativeExpression() { + Object target = new TestTransformer(); + MethodInvokingTransformer transformer = new MethodInvokingTransformer(target, "evalFoo"); + MessageTransformingHandler handler = new MessageTransformingHandler(transformer); + handler.afterPropertiesSet(); + QueueChannel outputChannel = new QueueChannel(); + handler.setOutputChannel(outputChannel); + handler.handleMessage(MessageBuilder.withPayload("test").setHeader("foo", "bar").build()); + Message result = outputChannel.receive(0); + assertNotNull(result); + assertEquals("BAR", result.getPayload()); + assertEquals("bar", result.getHeaders().get("foo")); + } + + + public static class TestTransformer { + + public String appendCorrelationId(Object payload, + @Header(value = MessageHeaders.CORRELATION_ID, required = true) Object correlationId) { + return payload.toString() + correlationId.toString(); + } + + public String appendFoo(Object payload, @Header(value = "foo") Object header) { + return payload.toString() + header.toString(); + } + + public String evalCorrelationId(@Header(value = MessageHeaders.CORRELATION_ID + ".toUpperCase()") String result) { + return result.toString(); + } + + public String evalFoo(@Header(value = "foo.toUpperCase()", required = true) String result) { + return result.toString(); + } + } + +}