diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MessageMappingMethodInvoker.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MessageMappingMethodInvoker.java index ef75b00d24..d1eba9b842 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MessageMappingMethodInvoker.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MessageMappingMethodInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -26,6 +26,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.springframework.core.annotation.AnnotationUtils; import org.springframework.integration.core.Message; import org.springframework.integration.message.MessageHandlingException; @@ -37,9 +40,6 @@ import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * A base or helper class for any Messaging component that acts as an adapter * by invoking a "plain" (not Message-aware) method on a given target object. @@ -48,6 +48,7 @@ import org.apache.commons.logging.LogFactory; * * @author Mark Fisher * @author Marius Bogoevici + * @see MethodParameterMessageMapper */ public class MessageMappingMethodInvoker { @@ -130,7 +131,28 @@ public class MessageMappingMethodInvoker { invoker = new DefaultMethodInvoker(this.object, method); this.invokers.put(method, invoker); } - result = invoker.invokeMethod(args); + try { + result = invoker.invokeMethod(args); + } + catch (NoSuchMethodException e) { + // fallback to replace the payload argument with headers if possible + boolean foundFallbackCandidate = false; + for (int i = 0; i < args.length; i++) { + if (message != null && message.getPayload().equals(args[i]) + && Map.class.isAssignableFrom(method.getParameterTypes()[i])) { + if (foundFallbackCandidate) { + // more than one, throw an Exception + throw new MessageHandlingException(message, "Failed to resolve ambiguity " + + "amongst multiple non-annotated candidates for matching Message headers.", e); + } + args[i] = message.getHeaders(); + foundFallbackCandidate = true; + } + } + if (foundFallbackCandidate) { + result = invoker.invokeMethod(args); + } + } } catch (IllegalArgumentException e) { try { @@ -158,6 +180,22 @@ public class MessageMappingMethodInvoker { else { args = new Object[] { mappingResult }; } + if (args.length > 1 && message != null && message.getPayload() instanceof Map) { + int mapArgCount = 0; + boolean resolvedMapArg = false; + for (int i = 0; i < args.length; i++) { + Object arg = args[i]; + if (arg instanceof Map && Map.class.isAssignableFrom(method.getParameterTypes()[i])) { + mapArgCount++; + if (arg.equals(message.getPayload())) { + // resolved if there is exactly one match + resolvedMapArg = !resolvedMapArg; + } + } + } + Assert.isTrue(resolvedMapArg || mapArgCount <= 1, + "Unable to resolve argument for Map-typed payload on method [" + method + "]."); + } return args; } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/message/MethodParameterMessageMapper.java b/org.springframework.integration/src/main/java/org/springframework/integration/message/MethodParameterMessageMapper.java index d431bbd4e8..4229e0bcd6 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/message/MethodParameterMessageMapper.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/message/MethodParameterMessageMapper.java @@ -63,12 +63,13 @@ import org.springframework.util.StringUtils; * expecting multiple headers (with or without the @Headers annotation). *

* If a Map or Properties object is expected, and the payload is not itself - * assignable to that type, then the MessageHeaders' values will be passed in - * the case of a Map-typed parameter, or the MessageHeaders' String-based values - * will be passed in the case of a Properties-typed parameter. In these cases - * multiple unannotated parameters are legal. If, however, the actual payload - * type is a Map or Properties instance, then this ambiguity cannot be - * resolved. For that reason, it is recommended to use the explicit + * assignable to that type or capable of being converted to that type, then + * the MessageHeaders' values will be passed in the case of a Map-typed + * parameter, or the MessageHeaders' String-based values will be passed in the + * case of a Properties-typed parameter. In these cases multiple unannotated + * parameters are legal. If, however, the actual payload type is a Map or + * Properties instance, then this ambiguity cannot be resolved. For that + * reason, it is highly recommended to use the explicit * {@link Headers @Headers} annotation whenever possible. *

* Some examples of legal method signatures:
@@ -215,7 +216,7 @@ public class MethodParameterMessageMapper implements InboundMessageMapper expectedType = metadata.getParameterType(); Header headerAnnotation = metadata.getHeaderAnnotation(); - if (metadata == payloadParameterMetadata) { + if (metadata == this.payloadParameterMetadata) { args[i] = message.getPayload(); } else if (headerAnnotation != null) { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodInvoker.java b/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodInvoker.java index d5fcf79abd..435db48e33 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodInvoker.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/util/DefaultMethodInvoker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2009 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. @@ -17,6 +17,7 @@ package org.springframework.integration.util; import java.lang.reflect.Method; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -78,12 +79,19 @@ public class DefaultMethodInvoker implements MethodInvoker { convertedArgs[i] = converter.convertIfNecessary(args[i], paramTypes[i]); } catch (TypeMismatchException e) { - throw new IllegalArgumentException("Failed to convert argument type.", e); + if (Map.class.isAssignableFrom(paramTypes[i])) { + // may be able to fallback to Message Headers for this argument + convertedArgs[i] = args[i]; + } + else { + throw new IllegalArgumentException("Failed to convert argument type.", e); + } } } this.method.setAccessible(true); if (this.logger.isDebugEnabled()) { - logger.debug("invoking method '" + this.method.getName() + "' with arguments " + ObjectUtils.nullSafeToString(convertedArgs)); + logger.debug("Invoking method [" + this.method + "] with arguments [" + + ObjectUtils.nullSafeToString(convertedArgs) + "]"); } try { return this.method.invoke(this.object, convertedArgs); @@ -93,6 +101,10 @@ public class DefaultMethodInvoker implements MethodInvoker { helper.setTargetObject(this.object); helper.setTargetMethod(this.method.getName()); helper.setArguments(convertedArgs); + if (logger.isDebugEnabled()) { + logger.debug("Attempting fallback based on method name [" + this.method.getName() + + "] with arguments [" + ObjectUtils.nullSafeToString(convertedArgs) + "]"); + } helper.prepare(); this.method = helper.getPreparedMethod(); return this.method.invoke(this.object, convertedArgs); diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/message/PayloadAndHeaderMappingTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/message/PayloadAndHeaderMappingTests.java index c3806a8014..334edd179b 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/message/PayloadAndHeaderMappingTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/message/PayloadAndHeaderMappingTests.java @@ -18,9 +18,11 @@ package org.springframework.integration.message; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -35,6 +37,7 @@ import org.springframework.integration.handler.ServiceActivatingHandler; /** * @author Mark Fisher + * @since 1.0.3 */ public class PayloadAndHeaderMappingTests { @@ -204,6 +207,192 @@ public class PayloadAndHeaderMappingTests { assertTrue(bean.lastHeaders.containsKey("baz")); } + @Test + public void headerMapOnlyWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("headerMapOnly", Map.class); + String payload = "test"; + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(payload, bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertTrue(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void headerMapOnlyWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("headerMapOnly", Map.class); + Map payload = new HashMap(); + payload.put("abc", 1); + payload.put("xyz", "test"); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertTrue(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void mapOnlyNoAnnotationsWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("mapOnlyNoAnnotations", Map.class); + Map payload = new HashMap(); + payload.put("payload", 1); + Map headers = new HashMap(); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertEquals(payload, bean.lastPayload); + assertNull(bean.lastHeaders); + } + + @Test + public void mapOnlyNoAnnotationsWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("mapOnlyNoAnnotations", Map.class); + String payload = "test"; + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertTrue(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void mapOnlyNoAnnotationsWithIntegerPayload() throws Exception { + MessageHandler handler = this.getHandler("mapOnlyNoAnnotations", Map.class); + Integer payload = new Integer(123); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertTrue(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void propertiesOnlyNoAnnotationsWithPropertiesPayload() throws Exception { + MessageHandler handler = this.getHandler("propertiesOnlyNoAnnotations", Properties.class); + Properties payload = new Properties(); + payload.setProperty("payload", "1"); + Map headers = new HashMap(); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertEquals(payload, bean.lastPayload); + assertNull(bean.lastHeaders); + } + + @Test + public void propertiesOnlyNoAnnotationsWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("propertiesOnlyNoAnnotations", Properties.class); + Map payload = new HashMap(); + payload.put("payload", 1); + Map headers = new HashMap(); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertEquals(payload, bean.lastPayload); + assertNull(bean.lastHeaders); + } + + @Test + public void propertiesOnlyNoAnnotationsWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("propertiesOnlyNoAnnotations", Properties.class); + String payload = "payload=abc"; + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastHeaders); + // String payload should have been converted to Properties + assertNotNull(bean.lastPayload); + assertTrue(bean.lastPayload instanceof Properties); + Properties payloadProps = (Properties) bean.lastPayload; + assertTrue(payloadProps.containsKey("payload")); + assertEquals("abc", payloadProps.get("payload")); + } + + @Test + public void propertiesOnlyNoAnnotationsWithIntegerPayload() throws Exception { + MessageHandler handler = this.getHandler("propertiesOnlyNoAnnotations", Properties.class); + Integer payload = new Integer(123); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + } + + @Test + public void headerPropertiesOnlyWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("headerPropertiesOnly", Properties.class); + String payload = "test"; + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertFalse(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void headerPropertiesOnlyWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("headerPropertiesOnly", Properties.class); + Map payload = new HashMap(); + payload.put("abc", 1); + payload.put("xyz", "test"); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertFalse(bean.lastHeaders.containsKey("baz")); + } + + @Test + public void headerPropertiesOnlyWithPropertiesPayload() throws Exception { + MessageHandler handler = this.getHandler("headerPropertiesOnly", Properties.class); + Properties payload = new Properties(); + payload.setProperty("abc", "1"); + payload.setProperty("xyz", "2"); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + headers.put("baz", 99); + Message message = MessageBuilder.withPayload(payload).copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertTrue(bean.lastHeaders.containsKey("foo")); + assertTrue(bean.lastHeaders.containsKey("bar")); + assertFalse(bean.lastHeaders.containsKey("baz")); + } + @Test public void payloadMapAndHeaderProperties() throws Exception { MessageHandler handler = this.getHandler("payloadMapAndHeaderProperties", Map.class, Properties.class); @@ -245,7 +434,7 @@ public class PayloadAndHeaderMappingTests { } @Test - public void twoMapsNoAnnotations() throws Exception { + public void twoMapsNoAnnotationsWithStringPayload() throws Exception { MessageHandler handler = this.getHandler("twoMapsNoAnnotations", Map.class, Map.class); Map headers = new HashMap(); headers.put("foo", "1"); @@ -259,6 +448,45 @@ public class PayloadAndHeaderMappingTests { assertEquals("2", bean.lastHeaders.get("bar2")); } + @Test(expected = MessageHandlingException.class) + public void twoMapsNoAnnotationsWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("twoMapsNoAnnotations", Map.class, Map.class); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Map payloadMap = new HashMap(); + payloadMap.put("baz", "99"); + Message message = MessageBuilder.withPayload(payloadMap).copyHeaders(headers).build(); + handler.handleMessage(message); + } + + @Test + public void twoMapsWithAnnotationsWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("twoMapsWithAnnotations", Map.class, Map.class); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload("test").copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("1", bean.lastHeaders.get("foo")); + assertEquals("2", bean.lastHeaders.get("bar")); + assertEquals("1", bean.lastHeaders.get("foo2")); + assertEquals("2", bean.lastHeaders.get("bar2")); + } + + @Test(expected = MessageHandlingException.class) + public void twoMapsWithAnnotationsWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("twoMapsWithAnnotations", Map.class, Map.class); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Map payloadMap = new HashMap(); + payloadMap.put("baz", "99"); + Message message = MessageBuilder.withPayload(payloadMap).copyHeaders(headers).build(); + handler.handleMessage(message); + } + @Test public void twoMapsNoAnnotationsAndObject() throws Exception { MessageHandler handler = this.getHandler("twoMapsNoAnnotationsAndObject", @@ -275,7 +503,7 @@ public class PayloadAndHeaderMappingTests { assertEquals("2", bean.lastHeaders.get("bar2")); } - @Test + @Test(expected = MessageHandlingException.class) public void twoMapsNoAnnotationsAndObjectWithMapPayload() throws Exception { MessageHandler handler = this.getHandler("twoMapsNoAnnotationsAndObject", Map.class, Object.class, Map.class); @@ -286,11 +514,6 @@ public class PayloadAndHeaderMappingTests { Message message = MessageBuilder.withPayload(payloadMap) .copyHeaders(headers).build(); handler.handleMessage(message); - assertEquals(payloadMap, bean.lastPayload); - assertEquals("1", bean.lastHeaders.get("foo")); - assertEquals("2", bean.lastHeaders.get("bar")); - assertEquals("1", bean.lastHeaders.get("foo2")); - assertEquals("2", bean.lastHeaders.get("bar2")); } @Test @@ -311,6 +534,150 @@ public class PayloadAndHeaderMappingTests { assertEquals("1", bean.lastHeaders.get("foo3")); } + @Test + public void singleStringHeaderOnlyWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("singleStringHeaderOnly", String.class); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload("test") + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("1", bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleStringHeaderOnlyWithIntegerPayload() throws Exception { + MessageHandler handler = this.getHandler("singleStringHeaderOnly", String.class); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload(new Integer(123)) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("1", bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleStringHeaderOnlyWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("singleStringHeaderOnly", String.class); + Map payload = new HashMap(); + payload.put("foo", 99); + Map headers = new HashMap(); + headers.put("foo", "1"); + headers.put("bar", "2"); + Message message = MessageBuilder.withPayload(payload) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("1", bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleIntegerHeaderOnlyWithIntegerPayload() throws Exception { + MessageHandler handler = this.getHandler("singleIntegerHeaderOnly", Integer.class); + Map headers = new HashMap(); + headers.put("foo", new Integer(123)); + headers.put("bar", new Integer(456)); + Message message = MessageBuilder.withPayload(new Integer(789)) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals(new Integer(123), bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleIntegerHeaderOnlyWithIntegerPayloadAndStringHeader() throws Exception { + MessageHandler handler = this.getHandler("singleIntegerHeaderOnly", Integer.class); + Map headers = new HashMap(); + headers.put("foo", "999"); + headers.put("bar", new Integer(456)); + Message message = MessageBuilder.withPayload(new Integer(789)) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals(new Integer(999), bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleIntegerHeaderOnlyWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("singleIntegerHeaderOnly", Integer.class); + Map headers = new HashMap(); + headers.put("foo", new Integer(123)); + headers.put("bar", new Integer(456)); + Message message = MessageBuilder.withPayload("test") + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals(new Integer(123), bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleObjectHeaderOnlyWithStringPayload() throws Exception { + MessageHandler handler = this.getHandler("singleObjectHeaderOnly", Object.class); + Map headers = new HashMap(); + headers.put("foo", "123"); + headers.put("bar", "456"); + Message message = MessageBuilder.withPayload("test") + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("123", bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleObjectHeaderOnlyWithObjectPayload() throws Exception { + MessageHandler handler = this.getHandler("singleObjectHeaderOnly", Object.class); + Map headers = new HashMap(); + headers.put("foo", "123"); + headers.put("bar", "456"); + Message message = MessageBuilder.withPayload(new Object()) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals("123", bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleObjectHeaderOnlyWithIntegerPayload() throws Exception { + MessageHandler handler = this.getHandler("singleObjectHeaderOnly", Object.class); + Map headers = new HashMap(); + headers.put("foo", new Integer(123)); + headers.put("bar", new Integer(456)); + Message message = MessageBuilder.withPayload(new Integer(789)) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals(new Integer(123), bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + + @Test + public void singleObjectHeaderOnlyWithMapPayload() throws Exception { + MessageHandler handler = this.getHandler("singleObjectHeaderOnly", Object.class); + Map payload = new HashMap(); + payload.put("foo", 99); + Map headers = new HashMap(); + headers.put("foo", new Integer(123)); + headers.put("bar", new Integer(456)); + Message message = MessageBuilder.withPayload(payload) + .copyHeaders(headers).build(); + handler.handleMessage(message); + assertNull(bean.lastPayload); + assertEquals(new Integer(123), bean.lastHeaders.get("foo")); + assertNull(bean.lastHeaders.get("bar")); + } + private ServiceActivatingHandler getHandler(String methodName, Class... types) throws Exception { return new ServiceActivatingHandler(bean, TestBean.class.getMethod(methodName, types)); @@ -389,6 +756,32 @@ public class PayloadAndHeaderMappingTests { this.lastPayload = payload; } + public void headerMapOnly(@Headers Map headers) { + this.lastHeaders = headers; + } + + public void headerPropertiesOnly(@Headers Properties headers) { + this.lastHeaders = headers; + } + + public void mapOnlyNoAnnotations(Map map) { + if (map.containsKey("payload")) { + this.lastPayload = map; + } + else { + this.lastHeaders = map; + } + } + + public void propertiesOnlyNoAnnotations(Properties props) { + if (props.containsKey("payload")) { + this.lastPayload = props; + } + else { + this.lastHeaders = props; + } + } + public void twoMapsNoAnnotations(Map map1, Map map2) { this.lastHeaders = new HashMap(map1); for (Map.Entry entry : map2.entrySet()) { @@ -396,6 +789,21 @@ public class PayloadAndHeaderMappingTests { } } + public void twoMapsWithAnnotations(@Headers Map map1, @Headers Map map2) { + this.lastHeaders = new HashMap(map1); + for (Map.Entry entry : map2.entrySet()) { + this.lastHeaders.put(entry.getKey() + "2", entry.getValue()); + } + } + + public void twoMapsWithAnnotationsAndObject(@Headers Map map1, Object o, @Headers Map map2) { + this.lastPayload = o; + this.lastHeaders = new HashMap(map1); + for (Map.Entry entry : map2.entrySet()) { + this.lastHeaders.put(entry.getKey() + "2", entry.getValue()); + } + } + public void twoMapsNoAnnotationsAndObject(Map map1, Object o, Map map2) { this.lastPayload = o; this.lastHeaders = new HashMap(map1); @@ -411,6 +819,18 @@ public class PayloadAndHeaderMappingTests { } this.lastHeaders.put("foo3", s); } + + public void singleStringHeaderOnly(@Header("foo") String s) { + this.lastHeaders = Collections.singletonMap("foo", s); + } + + public void singleIntegerHeaderOnly(@Header("foo") Integer n) { + this.lastHeaders = Collections.singletonMap("foo", n); + } + + public void singleObjectHeaderOnly(@Header("foo") Object o) { + this.lastHeaders = Collections.singletonMap("foo", o); + } } }