diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/annotation/MessageMapping.java b/org.springframework.integration/src/main/java/org/springframework/integration/annotation/Payload.java similarity index 67% rename from org.springframework.integration/src/main/java/org/springframework/integration/annotation/MessageMapping.java rename to org.springframework.integration/src/main/java/org/springframework/integration/annotation/Payload.java index 9f15c2c77c..bc33141806 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/annotation/MessageMapping.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/annotation/Payload.java @@ -24,10 +24,12 @@ import java.lang.annotation.Target; /** * This annotation allows you to specify a SpEL expression indicating that a method - * parameter's value should be mapped from the result of expression processing. - * The annotated parameter must be of the required type. - * Example: void foo(@MessageMapping("headers.day") String arg) - will map the value of - * the 'day' header to 'arg'. + * parameter's value should be mapped from the payload of a Message. The expression + * will be evaluated against the payload object as the root context. The annotated + * parameter type must match or be convertible from the evaluation result. + *

+ * Example: void foo(@Payload("city.name") String cityName) - will map the value of + * the 'name' property of the 'city' property of the payload object. * * @author Oleg Zhurakousky * @since 2.0 @@ -35,8 +37,11 @@ import java.lang.annotation.Target; @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented -public @interface MessageMapping { +public @interface Payload { - String value(); + /** + * Expression for matching against nested properties of the payload. + */ + String value() default ""; } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java index 85711c71ef..05e07d5abf 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java @@ -40,7 +40,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.annotation.Header; import org.springframework.integration.annotation.Headers; -import org.springframework.integration.annotation.MessageMapping; +import org.springframework.integration.annotation.Payload; import org.springframework.integration.core.Message; import org.springframework.integration.message.InboundMessageMapper; import org.springframework.integration.message.MessageBuilder; @@ -168,8 +168,14 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper toMessage(Object[] arguments) { - Assert.notNull(arguments, "Can not map 'null' arguments to Message"); + Assert.notNull(arguments, "cannot map null arguments to Message"); if (arguments.length > this.parameterList.size()) { throw new IllegalArgumentException("Too many parameters provided for: " + method); } @@ -206,10 +212,10 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper type = annotation.annotationType(); - if (type.equals(MessageMapping.class) || type.equals(Header.class) || type.equals(Headers.class)) { + if (type.equals(Payload.class) || type.equals(Header.class) || type.equals(Headers.class)) { if (match != null) { throw new IllegalArgumentException("at most one parameter annotation can be provided for message mapping, " + - "but found two [" + match.annotationType().getName() + "] and [" + annotation.annotationType().getName() + "]"); + "but found two: [" + match.annotationType().getName() + "] and [" + annotation.annotationType().getName() + "]"); } match = annotation; } @@ -250,9 +256,9 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper message = MessageBuilder.withPayload("payload").setHeader("emp", employee).build(); Object[] args = mapper.fromMessage(message); assertEquals("John", args[0]); - assertEquals("Doe", args[1]); + assertEquals("DOE", args[1]); } @SuppressWarnings("unused") private static class MultipleMappingAnnotationTestBean { - public void test(@MessageMapping("payload") @Header("foo") String s) { + public void test(@Payload("payload") @Header("foo") String s) { } } @@ -334,7 +334,8 @@ public class ArgumentArrayMessageMapperFromMessageTests { return num; } - public String headersWithExpressions(@Header("emp.fname") String firstName, @Header("emp.lname") String lastName) { + public String headersWithExpressions(@Header("emp.fname") String firstName, + @Header("emp.lname.toUpperCase()") String lastName) { return lastName + ", " + firstName; } @@ -373,20 +374,20 @@ public class ArgumentArrayMessageMapperFromMessageTests { return i; } - public void fromMessageToArgWithConversion(@MessageMapping("headers.number") String sArg) {} // + public void fromMessageToArgWithConversion(@Header("number") String sArg) {} // - public void fromMessageToArgWithConversion(@MessageMapping("headers.number") Integer iArg) {} // + public void fromMessageToArgWithConversion(@Header("number") Integer iArg) {} // public void fromMessageToArgWithConversion(@Header("numberA")Integer valueA, @Header("numberB") Integer valueB) {} // - public void fromMessageToMessageMappingAnnotation(@MessageMapping("headers.day") String value) {} // + public void fromMessageToMessageMappingAnnotation(@Header("day") String value) {} // - public void fromMessageToMessageMappingAnnotationMultiArguments(@MessageMapping("headers.day") String argA, - @MessageMapping("headers.month") String argB, - @MessageMapping("#this") Message message, - @MessageMapping("payload") Employee payloadArg, - @MessageMapping("payload.fname") String value, - @MessageMapping("headers") Map headers){} // + public void fromMessageToMessageMappingAnnotationMultiArguments(@Header("day") String argA, + @Header("month") String argB, + Message message, + @Payload Employee payloadArg, + @Payload("fname") String value, + @Headers Map headers){} // public void fromMessageIrrelevantAnnotation(@BogusAnnotation() String value){} // } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/handler/ArgumentArrayMessageMapperToMessageTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/handler/ArgumentArrayMessageMapperToMessageTests.java index d3d948110f..306131577b 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/handler/ArgumentArrayMessageMapperToMessageTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/handler/ArgumentArrayMessageMapperToMessageTests.java @@ -27,7 +27,6 @@ import org.junit.Test; import org.springframework.integration.annotation.Header; import org.springframework.integration.annotation.Headers; -import org.springframework.integration.annotation.MessageMapping; import org.springframework.integration.core.Message; import org.springframework.integration.handler.ArgumentArrayMessageMapper; import org.springframework.integration.message.MessageBuilder;