diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/DefaultMessageHandlerAdapter.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/DefaultMessageHandlerAdapter.java index e7eae7c9e0..276534a842 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/DefaultMessageHandlerAdapter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/DefaultMessageHandlerAdapter.java @@ -16,25 +16,41 @@ package org.springframework.integration.handler; -import org.springframework.beans.factory.InitializingBean; import org.springframework.core.Ordered; import org.springframework.integration.message.Message; -import org.springframework.integration.message.MessageMapper; import org.springframework.integration.util.SimpleMethodInvoker; /** * An implementation of {@link MessageHandler} that invokes the specified method - * on the provided target object. It then uses a {@link MessageMapper} strategy - * for converting the object to a {@link Message}. If the method has a non-null - * return value, a reply message will be generated by the mapper. + * on the provided target object. If {@link #shouldUseMapperOnInvocation} is set + * to true (the default), it will use the provided + * {@link org.springframework.integration.message.MessageMapper} strategy to + * convert the inbound {@link Message} to an object that will be passed as the + * method parameter. If the method has a non-null return value, a reply message + * will be generated by the mapper. * * @author Mark Fisher */ -public class DefaultMessageHandlerAdapter extends AbstractMessageHandlerAdapter - implements Ordered, InitializingBean { +public class DefaultMessageHandlerAdapter extends AbstractMessageHandlerAdapter implements Ordered { + + private boolean shouldUseMapperOnInvocation = true; + + + /** + * Specify whether the handler method should use the + * {@link org.springframework.integration.message.MessageMapper} when + * invoking the target method. Default is true. To force + * passing the {@link Message} directly, set this to false. + */ + public void setShouldUseMapperOnInvocation(boolean shouldUseMapperOnInvocation) { + this.shouldUseMapperOnInvocation = shouldUseMapperOnInvocation; + } public Object doHandle(Message message, SimpleMethodInvoker invoker) { - return invoker.invokeMethod(this.getMapper().fromMessage(message)); + if (this.shouldUseMapperOnInvocation) { + return invoker.invokeMethod(this.getMapper().fromMessage(message)); + } + return invoker.invokeMethod(message); } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/config/AbstractMessageHandlerCreator.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/config/AbstractMessageHandlerCreator.java index 56aa3c3ce3..6debd75e1d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/config/AbstractMessageHandlerCreator.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/config/AbstractMessageHandlerCreator.java @@ -19,8 +19,10 @@ package org.springframework.integration.handler.config; import java.lang.reflect.Method; import java.util.Map; +import org.springframework.beans.factory.InitializingBean; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.Order; +import org.springframework.integration.MessagingConfigurationException; import org.springframework.integration.handler.AbstractMessageHandlerAdapter; import org.springframework.integration.handler.MessageHandler; @@ -43,6 +45,14 @@ public abstract class AbstractMessageHandlerCreator implements MessageHandlerCre adapter.setOrder(orderAnnotation.value()); } } + if (handler instanceof InitializingBean) { + try { + ((InitializingBean) handler).afterPropertiesSet(); + } + catch (Exception e) { + throw new MessagingConfigurationException("failed to initialize handler", e); + } + } return handler; } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreator.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreator.java index f767594b25..4a05bbf46d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreator.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreator.java @@ -20,8 +20,10 @@ import java.lang.reflect.Method; import java.util.Map; import org.springframework.core.annotation.Order; +import org.springframework.integration.MessagingConfigurationException; import org.springframework.integration.handler.DefaultMessageHandlerAdapter; import org.springframework.integration.handler.MessageHandler; +import org.springframework.integration.message.Message; /** * Default implementation of the handler creator strategy that creates a @@ -34,7 +36,14 @@ import org.springframework.integration.handler.MessageHandler; public class DefaultMessageHandlerCreator extends AbstractMessageHandlerCreator { public MessageHandler doCreateHandler(Object object, Method method, Map attributes) { - return new DefaultMessageHandlerAdapter(); + Class[] types = method.getParameterTypes(); + if (types.length != 1) { + throw new MessagingConfigurationException("exactly one method parameter is required"); + } + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + boolean expectsMessage = (Message.class.isAssignableFrom(types[0])); + adapter.setShouldUseMapperOnInvocation(!expectsMessage); + return adapter; } } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/DefaultMessageHandlerAdapterTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/DefaultMessageHandlerAdapterTests.java new file mode 100644 index 0000000000..a7c489107a --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/DefaultMessageHandlerAdapterTests.java @@ -0,0 +1,108 @@ +/* + * Copyright 2002-2007 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 org.junit.Test; + +import org.springframework.integration.message.Message; +import org.springframework.integration.message.StringMessage; + +/** + * @author Mark Fisher + */ +public class DefaultMessageHandlerAdapterTests { + + @Test + public void testPayloadAsMethodParameterAndObjectAsReturnValue() { + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + adapter.setObject(new TestHandler()); + adapter.setMethodName("acceptPayloadAndReturnObject"); + adapter.afterPropertiesSet(); + Message result = adapter.handle(new StringMessage("testing")); + assertEquals("testing-1", result.getPayload()); + } + + @Test + public void testPayloadAsMethodParameterAndMessageAsReturnValue() { + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + adapter.setObject(new TestHandler()); + adapter.setMethodName("acceptPayloadAndReturnMessage"); + adapter.afterPropertiesSet(); + Message result = adapter.handle(new StringMessage("testing")); + assertEquals("testing-2", result.getPayload()); + } + + @Test + public void testMessageAsMethodParameterAndObjectAsReturnValue() { + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + adapter.setShouldUseMapperOnInvocation(false); + adapter.setObject(new TestHandler()); + adapter.setMethodName("acceptMessageAndReturnObject"); + adapter.afterPropertiesSet(); + Message result = adapter.handle(new StringMessage("testing")); + assertEquals("testing-3", result.getPayload()); + } + + @Test + public void testMessageAsMethodParameterAndMessageAsReturnValue() { + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + adapter.setShouldUseMapperOnInvocation(false); + adapter.setObject(new TestHandler()); + adapter.setMethodName("acceptMessageAndReturnMessage"); + adapter.afterPropertiesSet(); + Message result = adapter.handle(new StringMessage("testing")); + assertEquals("testing-4", result.getPayload()); + } + + @Test + public void testMessageSubclassAsMethodParameterAndMessageAsReturnValue() { + DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter(); + adapter.setShouldUseMapperOnInvocation(false); + adapter.setObject(new TestHandler()); + adapter.setMethodName("acceptMessageSubclassAndReturnMessage"); + adapter.afterPropertiesSet(); + Message result = adapter.handle(new StringMessage("testing")); + assertEquals("testing-5", result.getPayload()); + } + + + private static class TestHandler { + + public String acceptPayloadAndReturnObject(String s) { + return s + "-1"; + } + + public Message acceptPayloadAndReturnMessage(String s) { + return new StringMessage(s + "-2"); + } + + public String acceptMessageAndReturnObject(Message m) { + return m.getPayload() + "-3"; + } + + public Message acceptMessageAndReturnMessage(Message m) { + return new StringMessage(m.getPayload() + "-4"); + } + + public Message acceptMessageSubclassAndReturnMessage(StringMessage m) { + return new StringMessage(m.getPayload() + "-5"); + } + } + +} diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreatorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreatorTests.java new file mode 100644 index 0000000000..c0a650e1b7 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/config/DefaultMessageHandlerCreatorTests.java @@ -0,0 +1,100 @@ +/* + * Copyright 2002-2007 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.config; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import org.springframework.integration.handler.MessageHandler; +import org.springframework.integration.message.Message; +import org.springframework.integration.message.StringMessage; + +/** + * @author Mark Fisher + */ +public class DefaultMessageHandlerCreatorTests { + + @Test + public void testPayloadAsMethodParameterAndObjectAsReturnValue() throws Exception { + DefaultMessageHandlerCreator creator = new DefaultMessageHandlerCreator(); + MessageHandler handler = creator.createHandler(new TestHandler(), + TestHandler.class.getMethod("acceptPayloadAndReturnObject", String.class), null); + Message result = handler.handle(new StringMessage("testing")); + assertEquals("testing-1", result.getPayload()); + } + + @Test + public void testPayloadAsMethodParameterAndMessageAsReturnValue() throws Exception { + DefaultMessageHandlerCreator creator = new DefaultMessageHandlerCreator(); + MessageHandler handler = creator.createHandler(new TestHandler(), + TestHandler.class.getMethod("acceptPayloadAndReturnMessage", String.class), null); + Message result = handler.handle(new StringMessage("testing")); + assertEquals("testing-2", result.getPayload()); + } + + @Test + public void testMessageAsMethodParameterAndObjectAsReturnValue() throws Exception { + DefaultMessageHandlerCreator creator = new DefaultMessageHandlerCreator(); + MessageHandler handler = creator.createHandler(new TestHandler(), + TestHandler.class.getMethod("acceptMessageAndReturnObject", Message.class), null); + Message result = handler.handle(new StringMessage("testing")); + assertEquals("testing-3", result.getPayload()); + } + + @Test + public void testMessageAsMethodParameterAndMessageAsReturnValue() throws Exception { + DefaultMessageHandlerCreator creator = new DefaultMessageHandlerCreator(); + MessageHandler handler = creator.createHandler(new TestHandler(), + TestHandler.class.getMethod("acceptMessageAndReturnMessage", Message.class), null); + Message result = handler.handle(new StringMessage("testing")); + assertEquals("testing-4", result.getPayload()); + } + + @Test + public void testMessageSubclassAsMethodParameterAndMessageAsReturnValue() throws Exception { + DefaultMessageHandlerCreator creator = new DefaultMessageHandlerCreator(); + MessageHandler handler = creator.createHandler(new TestHandler(), + TestHandler.class.getMethod("acceptMessageSubclassAndReturnMessage", StringMessage.class), null); + Message result = handler.handle(new StringMessage("testing")); + assertEquals("testing-5", result.getPayload()); + } + + + private static class TestHandler { + + public String acceptPayloadAndReturnObject(String s) { + return s + "-1"; + } + + public Message acceptPayloadAndReturnMessage(String s) { + return new StringMessage(s + "-2"); + } + + public String acceptMessageAndReturnObject(Message m) { + return m.getPayload() + "-3"; + } + + public Message acceptMessageAndReturnMessage(Message m) { + return new StringMessage(m.getPayload() + "-4"); + } + + public Message acceptMessageSubclassAndReturnMessage(StringMessage m) { + return new StringMessage(m.getPayload() + "-5"); + } + } +}