Added header-copying constructor to GenericMessage (INT-123). Also simplified the AbstractMessageHandlerAdapter.
This commit is contained in:
@@ -21,9 +21,10 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageHeader;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.message.SimplePayloadMessageMapper;
|
||||
import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -45,8 +46,6 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
|
||||
|
||||
private volatile String methodName;
|
||||
|
||||
private volatile MessageMapper mapper = new SimplePayloadMessageMapper();
|
||||
|
||||
private volatile SimpleMethodInvoker<T> invoker;
|
||||
|
||||
private volatile int order = Integer.MAX_VALUE;
|
||||
@@ -61,28 +60,11 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
protected Object getObject() {
|
||||
return this.object;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
Assert.notNull(methodName, "'methodName' must not be null");
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return this.methodName;
|
||||
}
|
||||
|
||||
public void setMapper(MessageMapper mapper) {
|
||||
Assert.notNull(mapper, "'mapper' must not be null");
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
protected MessageMapper getMapper() {
|
||||
return this.mapper;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
@@ -94,22 +76,22 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
|
||||
public final void afterPropertiesSet() {
|
||||
this.validate();
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
this.invoker = new SimpleMethodInvoker<T>(this.object, this.methodName);
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.initialized;
|
||||
}
|
||||
}
|
||||
|
||||
public final Message<?> handle(Message<?> message) {
|
||||
if (!this.initialized) {
|
||||
this.afterPropertiesSet();
|
||||
}
|
||||
Object result = this.doHandle(message, invoker);
|
||||
if (result != null) {
|
||||
Message<?> reply = (result instanceof Message) ? (Message<?>) result :
|
||||
this.mapper.toMessage(result);
|
||||
this.createReplyMessage(result, message.getHeader());
|
||||
Object correlationId = reply.getHeader().getCorrelationId();
|
||||
if (correlationId == null) {
|
||||
Object orginalCorrelationId = message.getHeader().getCorrelationId();
|
||||
@@ -127,6 +109,10 @@ public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler
|
||||
protected void validate() {
|
||||
}
|
||||
|
||||
protected Message<?> createReplyMessage(Object payload, MessageHeader originalMessageHeader) {
|
||||
return new GenericMessage(payload, originalMessageHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method. The invoker has been created for
|
||||
* the provided target object and method. May return an object of type
|
||||
|
||||
@@ -33,24 +33,23 @@ import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
*/
|
||||
public class DefaultMessageHandlerAdapter<T> extends AbstractMessageHandlerAdapter<T> implements Ordered {
|
||||
|
||||
private boolean shouldUseMapperOnInvocation = true;
|
||||
|
||||
private boolean expectsMessage = false;
|
||||
|
||||
/**
|
||||
* Specify whether the handler method should use the
|
||||
* {@link org.springframework.integration.message.MessageMapper} when
|
||||
* invoking the target method. Default is <code>true</code>. To force
|
||||
* passing the {@link Message} directly, set this to <code>false</code>.
|
||||
* Specify whether the handler should pass the message when invoking the
|
||||
* target method. The default is <code>false</code> indicating that the
|
||||
* message's <em>payload</em> should be passed as the argument. To force
|
||||
* passing the {@link Message} directly, set this to <code>true</code>.
|
||||
*/
|
||||
public void setShouldUseMapperOnInvocation(boolean shouldUseMapperOnInvocation) {
|
||||
this.shouldUseMapperOnInvocation = shouldUseMapperOnInvocation;
|
||||
public void setExpectsMessage(boolean expectsMessage) {
|
||||
this.expectsMessage = expectsMessage;
|
||||
}
|
||||
|
||||
public Object doHandle(Message message, SimpleMethodInvoker invoker) {
|
||||
if (this.shouldUseMapperOnInvocation) {
|
||||
return invoker.invokeMethod(this.getMapper().fromMessage(message));
|
||||
if (this.expectsMessage) {
|
||||
return invoker.invokeMethod(message);
|
||||
}
|
||||
return invoker.invokeMethod(message);
|
||||
return invoker.invokeMethod(message.getPayload());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ public class DefaultMessageHandlerCreator extends AbstractMessageHandlerCreator
|
||||
throw new MessagingConfigurationException("exactly one method parameter is required");
|
||||
}
|
||||
DefaultMessageHandlerAdapter<Object> adapter = new DefaultMessageHandlerAdapter<Object>();
|
||||
boolean expectsMessage = (Message.class.isAssignableFrom(types[0]));
|
||||
adapter.setShouldUseMapperOnInvocation(!expectsMessage);
|
||||
adapter.setExpectsMessage(Message.class.isAssignableFrom(types[0]));
|
||||
return adapter;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
package org.springframework.integration.message;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.integration.util.RandomUuidGenerator;
|
||||
import org.springframework.integration.util.IdGenerator;
|
||||
import org.springframework.integration.util.RandomUuidGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -63,6 +64,11 @@ public class GenericMessage<T> implements Message<T> {
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public GenericMessage(T payload, MessageHeader headerToCopy) {
|
||||
this(payload);
|
||||
this.copyHeader(headerToCopy);
|
||||
}
|
||||
|
||||
|
||||
public Object getId() {
|
||||
return this.id;
|
||||
@@ -85,4 +91,16 @@ public class GenericMessage<T> implements Message<T> {
|
||||
return "[ID=" + this.id + "][Header=" + this.header + "][Payload='" + this.payload + "']";
|
||||
}
|
||||
|
||||
private void copyHeader(final MessageHeader headerToCopy) {
|
||||
Set<String> propertyNames = headerToCopy.getPropertyNames();
|
||||
for (String key : propertyNames) {
|
||||
this.header.setProperty(key, headerToCopy.getProperty(key));
|
||||
}
|
||||
Set<String> attributeNames = headerToCopy.getAttributeNames();
|
||||
for (String key : attributeNames) {
|
||||
this.header.setAttribute(key, headerToCopy.getAttribute(key));
|
||||
}
|
||||
this.header.setReturnAddress(headerToCopy.getReturnAddress());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.integration.message;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* A holder for Message metadata. This includes information that may be used by
|
||||
@@ -48,7 +48,7 @@ public class MessageHeader {
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
||||
private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
|
||||
/**
|
||||
@@ -110,8 +110,8 @@ public class MessageHeader {
|
||||
return this.properties.getProperty(key);
|
||||
}
|
||||
|
||||
public void setProperty(String key, String value) {
|
||||
this.properties.setProperty(key, value);
|
||||
public String setProperty(String key, String value) {
|
||||
return (String) this.properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
public Set<String> getPropertyNames() {
|
||||
@@ -126,8 +126,12 @@ public class MessageHeader {
|
||||
return this.attributes.get(key);
|
||||
}
|
||||
|
||||
public void setAttribute(String key, Object value) {
|
||||
this.attributes.put(key, value);
|
||||
public Object setAttribute(String key, Object value) {
|
||||
return this.attributes.put(key, value);
|
||||
}
|
||||
|
||||
public Object setAttributeIfAbsent(String key, Object value) {
|
||||
return this.attributes.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
public Set<String> getAttributeNames() {
|
||||
|
||||
@@ -67,9 +67,6 @@ public class RouterMessageHandlerAdapter extends AbstractMessageHandlerAdapter i
|
||||
|
||||
@Override
|
||||
protected Object doHandle(Message message, SimpleMethodInvoker invoker) {
|
||||
if (!this.isInitialized()) {
|
||||
this.afterPropertiesSet();
|
||||
}
|
||||
if (method.getParameterTypes().length != 1) {
|
||||
throw new MessagingConfigurationException(
|
||||
"method must accept exactly one parameter");
|
||||
|
||||
@@ -51,7 +51,7 @@ public class DefaultMessageHandlerAdapterTests {
|
||||
@Test
|
||||
public void testMessageAsMethodParameterAndObjectAsReturnValue() {
|
||||
DefaultMessageHandlerAdapter<TestHandler> adapter = new DefaultMessageHandlerAdapter<TestHandler>();
|
||||
adapter.setShouldUseMapperOnInvocation(false);
|
||||
adapter.setExpectsMessage(true);
|
||||
adapter.setObject(new TestHandler());
|
||||
adapter.setMethodName("acceptMessageAndReturnObject");
|
||||
adapter.afterPropertiesSet();
|
||||
@@ -62,7 +62,7 @@ public class DefaultMessageHandlerAdapterTests {
|
||||
@Test
|
||||
public void testMessageAsMethodParameterAndMessageAsReturnValue() {
|
||||
DefaultMessageHandlerAdapter<TestHandler> adapter = new DefaultMessageHandlerAdapter<TestHandler>();
|
||||
adapter.setShouldUseMapperOnInvocation(false);
|
||||
adapter.setExpectsMessage(true);
|
||||
adapter.setObject(new TestHandler());
|
||||
adapter.setMethodName("acceptMessageAndReturnMessage");
|
||||
adapter.afterPropertiesSet();
|
||||
@@ -73,7 +73,7 @@ public class DefaultMessageHandlerAdapterTests {
|
||||
@Test
|
||||
public void testMessageSubclassAsMethodParameterAndMessageAsReturnValue() {
|
||||
DefaultMessageHandlerAdapter<TestHandler> adapter = new DefaultMessageHandlerAdapter<TestHandler>();
|
||||
adapter.setShouldUseMapperOnInvocation(false);
|
||||
adapter.setExpectsMessage(true);
|
||||
adapter.setObject(new TestHandler());
|
||||
adapter.setMethodName("acceptMessageSubclassAndReturnMessage");
|
||||
adapter.afterPropertiesSet();
|
||||
@@ -84,7 +84,7 @@ public class DefaultMessageHandlerAdapterTests {
|
||||
@Test
|
||||
public void testMessageSubclassAsMethodParameterAndMessageSubclassAsReturnValue() {
|
||||
DefaultMessageHandlerAdapter<TestHandler> adapter = new DefaultMessageHandlerAdapter<TestHandler>();
|
||||
adapter.setShouldUseMapperOnInvocation(false);
|
||||
adapter.setExpectsMessage(true);
|
||||
adapter.setObject(new TestHandler());
|
||||
adapter.setMethodName("acceptMessageSubclassAndReturnMessageSubclass");
|
||||
adapter.afterPropertiesSet();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.message;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -55,4 +56,14 @@ public class GenericMessageTests {
|
||||
assertFalse(message.isExpired());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMessageHeaderCopied() {
|
||||
MessageHeader header = new MessageHeader();
|
||||
header.setAttribute("testAttribute", new Integer(123));
|
||||
header.setProperty("testProperty", "foo");
|
||||
GenericMessage<String> message = new GenericMessage<String>("test", header);
|
||||
assertEquals(new Integer(123), message.getHeader().getAttribute("testAttribute"));
|
||||
assertEquals("foo", message.getHeader().getProperty("testProperty"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
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;
|
||||
@@ -39,24 +40,55 @@ public class MessageHeaderTests {
|
||||
@Test
|
||||
public void testAttributes() {
|
||||
MessageHeader header = new MessageHeader();
|
||||
Integer integer = new Integer(123);
|
||||
header.setAttribute("test", integer);
|
||||
assertEquals(integer, header.getAttribute("test"));
|
||||
Integer value = new Integer(123);
|
||||
Object previousValue = header.setAttribute("test", value);
|
||||
assertNull(previousValue);
|
||||
assertEquals(value, header.getAttribute("test"));
|
||||
assertNull(header.getAttribute("nosuchattribute"));
|
||||
Set<String> names = header.getAttributeNames();
|
||||
assertEquals(1, names.size());
|
||||
assertTrue(names.contains("test"));
|
||||
Integer newValue = new Integer(456);
|
||||
previousValue = header.setAttribute("test", newValue);
|
||||
assertEquals(value, previousValue);
|
||||
assertEquals(newValue, header.getAttribute("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProperties() {
|
||||
MessageHeader header = new MessageHeader();
|
||||
header.setProperty("foo", "bar");
|
||||
String previousValue = header.setProperty("foo", "bar");
|
||||
assertNull(previousValue);
|
||||
assertEquals("bar", header.getProperty("foo"));
|
||||
assertNull(header.getProperty("nosuchproperty"));
|
||||
Set<String> names = header.getPropertyNames();
|
||||
assertEquals(1, names.size());
|
||||
assertTrue(names.contains("foo"));
|
||||
previousValue = header.setProperty("foo", "baz");
|
||||
assertEquals("bar", previousValue);
|
||||
assertEquals("baz", header.getProperty("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeIfAbsent() {
|
||||
MessageHeader header = new MessageHeader();
|
||||
Integer integer = new Integer(123);
|
||||
assertNull(header.getAttribute("test"));
|
||||
assertFalse(header.getAttributeNames().contains("test"));
|
||||
Object existingValue = header.setAttributeIfAbsent("test", integer);
|
||||
assertNull(existingValue);
|
||||
assertEquals(integer, header.getAttribute("test"));
|
||||
assertTrue(header.getAttributeNames().contains("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeIfAbsentDoesNotOverride() {
|
||||
MessageHeader header = new MessageHeader();
|
||||
Integer originalValue = new Integer(123);
|
||||
header.setAttributeIfAbsent("test", originalValue);
|
||||
Object existingValue = header.setAttributeIfAbsent("test", new Integer(456));
|
||||
assertEquals(originalValue, header.getAttribute("test"));
|
||||
assertEquals(originalValue, existingValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user