diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/AbstractMessageHandlerAdapter.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/AbstractMessageHandlerAdapter.java deleted file mode 100644 index 908d6d19ed..0000000000 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/AbstractMessageHandlerAdapter.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.handler; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -import org.springframework.integration.channel.ChannelRegistry; -import org.springframework.integration.channel.ChannelRegistryAware; -import org.springframework.integration.message.DefaultMessageCreator; -import org.springframework.integration.message.DefaultMessageMapper; -import org.springframework.integration.message.Message; -import org.springframework.integration.message.MessageBuilder; -import org.springframework.integration.message.MessageCreator; -import org.springframework.integration.message.MessageHandlingException; -import org.springframework.integration.message.MessageHeaders; -import org.springframework.integration.message.MessageMapper; -import org.springframework.integration.util.AbstractMethodInvokingAdapter; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; - -/** - * An implementation of the {@link MessageHandler} interface that invokes the specified method and target object. Either - * a {@link Method} reference or a 'methodName' may be provided, but both are not necessary. In fact, while preference - * is given to a {@link Method} reference if available, an Exception will be thrown if a non-matching 'methodName' has - * also been provided. Therefore, to avoid such ambiguity, it is recommended to provide just one or the other. - *

- * This handler also accepts an implementation of the {@link MessageMapper} strategy interface which it uses for - * converting from the {@link Message} being handled to an Object prior to invoking the method. Likewise, if the method - * has a non-null return value, a reply message will be generated by the configured implementation of the - * {@link MessageCreator} strategy interface. In both cases, the default implementations will simply consider the - * message's payload. - * - * @author Mark Fisher - */ -public abstract class AbstractMessageHandlerAdapter extends AbstractMethodInvokingAdapter - implements MessageHandler, ChannelRegistryAware { - - public static final String OUTPUT_CHANNEL_NAME_KEY = "outputChannelName"; - - - private volatile boolean methodExpectsMessage; - - private volatile MessageMapper messageMapper = new DefaultMessageMapper(); - - private volatile MessageCreator messageCreator = new DefaultMessageCreator(); - - private volatile ChannelRegistry channelRegistry; - - - public void setMethodExpectsMessage(boolean methodExpectsMessage) { - this.methodExpectsMessage = methodExpectsMessage; - } - - public void setMessageMapper(MessageMapper messageMapper) { - Assert.notNull(messageMapper, "'messageMapper' must not be null"); - this.messageMapper = messageMapper; - } - - public void setMessageCreator(MessageCreator messageCreator) { - Assert.notNull(messageCreator, "'messageCreator' must not be null"); - this.messageCreator = messageCreator; - } - - public void setChannelRegistry(ChannelRegistry channelRegistry) { - this.channelRegistry = channelRegistry; - } - - protected ChannelRegistry getChannelRegistry() { - return this.channelRegistry; - } - - public Message handle(Message message) { - if (!this.isInitialized()) { - this.afterPropertiesSet(); - } - if (message == null) { - throw new IllegalArgumentException("message must not be null"); - } - Object args[] = null; - Object mappingResult = (this.methodExpectsMessage) ? message : this.messageMapper.mapMessage(message); - if (mappingResult != null && mappingResult.getClass().isArray() - && (Object.class.isAssignableFrom(mappingResult.getClass().getComponentType()))) { - args = (Object[]) mappingResult; - } - else { - args = new Object[] { mappingResult }; - } - try { - Object result = null; - try { - result = this.invokeMethod(args); - } - catch (NoSuchMethodException e) { - result = this.invokeMethod(message); - this.methodExpectsMessage = true; - } - if (result == null) { - return null; - } - return this.handleReturnValue(result, message); - } - catch (InvocationTargetException e) { - throw new MessageHandlingException(message, "Handler method '" - + this.getMethodName() + "' threw an Exception.", e.getTargetException()); - } - catch (Throwable e) { - throw new MessageHandlingException(message, "Failed to invoke handler method '" - + this.getMethodName() + "' with arguments: " + ObjectUtils.nullSafeToString(args), e); - } - } - - protected Message createReplyMessage(Object returnValue, Message originalMessage) { - Message reply = this.messageCreator.createMessage(returnValue); - if (reply == null) { - return null; - } - return MessageBuilder.fromMessage(reply).copyHeadersIfAbsent(originalMessage.getHeaders()) - .setHeaderIfAbsent(MessageHeaders.CORRELATION_ID, originalMessage.getHeaders().getId()).build(); - } - - /** - * Subclasses must implement this method to handle the return value. - */ - protected abstract Message handleReturnValue(Object returnValue, Message originalMessage); - -} diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/transformer/MethodInvokingPayloadTransformer.java b/org.springframework.integration/src/main/java/org/springframework/integration/transformer/MethodInvokingPayloadTransformer.java index c662d0f766..831fdabe2e 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/transformer/MethodInvokingPayloadTransformer.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/transformer/MethodInvokingPayloadTransformer.java @@ -16,15 +16,53 @@ package org.springframework.integration.transformer; -import org.springframework.integration.util.AbstractMethodInvokingAdapter; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.integration.ConfigurationException; +import org.springframework.integration.util.MethodInvoker; +import org.springframework.integration.util.NameResolvingMethodInvoker; /** * @author Mark Fisher */ -public class MethodInvokingPayloadTransformer extends AbstractMethodInvokingAdapter implements PayloadTransformer { +public class MethodInvokingPayloadTransformer implements PayloadTransformer, InitializingBean { + + private volatile Object object; + + private volatile String methodName; + + private volatile MethodInvoker invoker; + + private volatile boolean initialized; + + private final Object initializationMonitor = new Object(); + + + public void setObject(Object object) { + this.object = object; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public void afterPropertiesSet() { + synchronized (this.initializationMonitor) { + if (this.initialized) { + return; + } + if (this.object == null || this.methodName == null) { + throw new ConfigurationException("the 'object' and 'methodName' are required"); + } + this.invoker = new NameResolvingMethodInvoker(this.object, this.methodName); + this.initialized = true; + } + } public Object transform(Object payload) throws Exception { - return this.invokeMethod(payload); + if (!this.initialized) { + this.afterPropertiesSet(); + } + return this.invoker.invokeMethod(payload); } } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/util/AbstractMethodInvokingAdapter.java b/org.springframework.integration/src/main/java/org/springframework/integration/util/AbstractMethodInvokingAdapter.java deleted file mode 100644 index 55a034e777..0000000000 --- a/org.springframework.integration/src/main/java/org/springframework/integration/util/AbstractMethodInvokingAdapter.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.util; - -import java.lang.reflect.Method; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.core.Ordered; -import org.springframework.integration.ConfigurationException; - -/** - * A base class for adapters that invoke a specified method and target object. - * Either a {@link Method} reference or a 'methodName' may be provided, but both - * are not necessary. In fact, while preference is given to a {@link Method} - * reference if available, an Exception will be thrown if a non-matching - * 'methodName' has also been provided. Therefore, to avoid such ambiguity, - * it is recommended to provide just one or the other. - * - * @author Mark Fisher - */ -public abstract class AbstractMethodInvokingAdapter implements MethodInvoker, InitializingBean, Ordered { - - protected final Log logger = LogFactory.getLog(this.getClass()); - - private volatile Object object; - - private volatile Method method; - - private volatile String methodName; - - private volatile int order; - - private volatile MethodInvoker invoker; - - private volatile boolean initialized; - - private final Object initializationMonitor = new Object(); - - - public void setObject(Object object) { - this.object = object; - } - - protected Object getObject() { - return this.object; - } - - public void setMethod(Method method) { - this.method = method; - } - - protected Method getMethod() { - return this.method; - } - - public void setMethodName(String methodName) { - this.methodName = methodName; - } - - protected String getMethodName() { - return this.methodName; - } - - public void setOrder(int order) { - this.order = order; - } - - public int getOrder() { - return order; - } - - protected boolean isInitialized() { - return this.initialized; - } - - public void afterPropertiesSet() { - synchronized (this.initializationMonitor) { - if (this.initialized) { - return; - } - if (this.object == null) { - throw new ConfigurationException("The target 'object' must not be null."); - } - if (this.method == null && this.methodName == null) { - throw new ConfigurationException("Either a 'method' or 'methodName' is required."); - } - if (this.method != null) { - if (this.methodName != null && !this.methodName.equals(this.method.getName())) { - throw new ConfigurationException("An ambiguity exists between the 'method' and 'methodName' properties. " + - "Note that only one of them is required, but if both are provided they must match."); - } - this.methodName = this.method.getName(); - this.invoker = new DefaultMethodInvoker(this.object, this.method); - } - else { - this.invoker = new NameResolvingMethodInvoker(this.object, this.methodName); - } - this.initialized = true; - } - this.initialize(); - } - - /** - * Subclasses may override this method for custom initialization requirements. - */ - protected void initialize() { - } - - public Object invokeMethod(Object ... args) throws Exception { - if (!this.initialized) { - this.afterPropertiesSet(); - } - return this.invoker.invokeMethod(args); - } - -} diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/handler/CorrelationIdTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/handler/CorrelationIdTests.java index 1e65e66e82..2f4968731f 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/handler/CorrelationIdTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/handler/CorrelationIdTests.java @@ -72,39 +72,26 @@ public class CorrelationIdTests { } @Test - public void testCorrelationNotPassedIfAlreadySetByHandler() throws Exception { + public void testCorrelationNotPassedFromRequestHeaderIfAlreadySetByHandler() throws Exception { Object correlationId = "123-ABC"; Message message = MessageBuilder.fromPayload("test") .setCorrelationId(correlationId).build(); - AbstractMessageHandlerAdapter adapter = new AbstractMessageHandlerAdapter() { - @Override - protected Message handleReturnValue(Object returnValue, Message originalMessage) { - Message resultMessage = this.createReplyMessage(returnValue, originalMessage); - return MessageBuilder.fromMessage(resultMessage) - .setCorrelationId("456-XYZ").build(); - } - }; - adapter.setObject(new TestBean()); - adapter.setMethodName("upperCase"); - adapter.afterPropertiesSet(); - Message reply = adapter.handle(message); + DefaultMessageHandler handler = new DefaultMessageHandler(); + handler.setObject(new TestBean()); + handler.setMethodName("createMessage"); + handler.afterPropertiesSet(); + Message reply = handler.handle(message); assertEquals("456-XYZ", reply.getHeaders().getCorrelationId()); } @Test - public void testCorrelationNotCopiedIfAlreadySetByHandler() throws Exception { + public void testCorrelationNotCopiedFromRequestMessgeIdIfAlreadySetByHandler() throws Exception { Message message = new StringMessage("test"); - AbstractMessageHandlerAdapter adapter = new AbstractMessageHandlerAdapter() { - @Override - protected Message handleReturnValue(Object returnValue, Message originalMessage) { - Message resultMessage = this.createReplyMessage(returnValue, originalMessage); - return MessageBuilder.fromMessage(resultMessage).setCorrelationId("456-XYZ").build(); - } - }; - adapter.setObject(new TestBean()); - adapter.setMethodName("upperCase"); - adapter.afterPropertiesSet(); - Message reply = adapter.handle(message); + DefaultMessageHandler handler = new DefaultMessageHandler(); + handler.setObject(new TestBean()); + handler.setMethodName("createMessage"); + handler.afterPropertiesSet(); + Message reply = handler.handle(message); assertEquals("456-XYZ", reply.getHeaders().getCorrelationId()); } @@ -134,6 +121,10 @@ public class CorrelationIdTests { public String[] split(String input) { return input.split(","); } + + public Message createMessage(String input) { + return MessageBuilder.fromPayload(input).setCorrelationId("456-XYZ").build(); + } } }