INT-2610 Fix Gateway Mapping Issue
Fix the inability for mappings by convention to be overriden with payload expression Cherry-pick PR #531
This commit is contained in:
committed by
Gary Russell
parent
a54bcf3cdf
commit
d2d9d67edb
@@ -23,6 +23,9 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
@@ -62,7 +65,7 @@ import org.springframework.util.StringUtils;
|
||||
* <tt>public void dealWith(Object payload, String payload);</tt><br/>
|
||||
* <tt>public void dealWith(Message message, Object payload);</tt><br/>
|
||||
* <tt>public void dealWith(Properties headers, Map payload);</tt><br/>
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Iwein Fuld
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -70,8 +73,9 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]>, BeanFactoryAware {
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private static final SpelExpressionParser PARSER = new SpelExpressionParser();
|
||||
|
||||
private final Method method;
|
||||
|
||||
@@ -91,7 +95,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
public GatewayMethodInboundMessageMapper(Method method) {
|
||||
this(method, null);
|
||||
}
|
||||
|
||||
|
||||
public GatewayMethodInboundMessageMapper(Method method, Map<String, Expression> headerExpressions) {
|
||||
Assert.notNull(method, "method must not be null");
|
||||
this.method = method;
|
||||
@@ -131,7 +135,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
messageOrPayload = this.payloadExpression.getValue(methodInvocationEvaluationContext);
|
||||
}
|
||||
for (int i = 0; i < this.parameterList.size(); i++) {
|
||||
Object argumentValue = arguments[i];
|
||||
Object argumentValue = arguments[i];
|
||||
MethodParameter methodParameter = this.parameterList.get(i);
|
||||
Annotation annotation = this.findMappingAnnotation(methodParameter.getParameterAnnotations());
|
||||
if (annotation != null) {
|
||||
@@ -161,7 +165,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
if (!(argumentValue instanceof Map)) {
|
||||
throw new IllegalArgumentException("@Headers annotation is only valid for Map-typed parameters");
|
||||
}
|
||||
for (Object key : ((Map<?, ?>) argumentValue).keySet()) {
|
||||
for (Object key : ((Map<?, ?>) argumentValue).keySet()) {
|
||||
Assert.isInstanceOf(String.class, key, "Invalid header name [" + key +
|
||||
"], name type must be String.");
|
||||
Object value = ((Map<?, ?>) argumentValue).get(key);
|
||||
@@ -175,8 +179,10 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
}
|
||||
else if (Map.class.isAssignableFrom(methodParameter.getParameterType())) {
|
||||
if (messageOrPayload instanceof Map && !foundPayloadAnnotation) {
|
||||
throw new MessagingException("Ambiguous method parameters; found more than one " +
|
||||
"Map-typed parameter and neither one contains a @Payload annotation");
|
||||
if (payloadExpression == null){
|
||||
throw new MessagingException("Ambiguous method parameters; found more than one " +
|
||||
"Map-typed parameter and neither one contains a @Payload annotation");
|
||||
}
|
||||
}
|
||||
this.copyHeaders((Map<?, ?>) argumentValue, headers);
|
||||
}
|
||||
@@ -240,13 +246,17 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
}
|
||||
|
||||
private void copyHeaders(Map<?, ?> argumentValue, Map<String, Object> headers) {
|
||||
for (Object key : argumentValue.keySet()) {
|
||||
for (Object key : argumentValue.keySet()) {
|
||||
if (!(key instanceof String)) {
|
||||
throw new IllegalArgumentException("Invalid header name [" + key +
|
||||
"], name type must be String.");
|
||||
if (this.logger.isWarnEnabled()){
|
||||
this.logger.warn("Invalid header name [" + key +
|
||||
"], name type must be String. Skipping mapping of this header to MessageHeaders.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
Object value = argumentValue.get(key);
|
||||
headers.put((String) key, value);
|
||||
}
|
||||
Object value = argumentValue.get(key);
|
||||
headers.put((String) key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +276,7 @@ class GatewayMethodInboundMessageMapper implements InboundMessageMapper<Object[]
|
||||
|
||||
private static List<MethodParameter> getMethodParameterList(Method method) {
|
||||
List<MethodParameter> parameterList = new LinkedList<MethodParameter>();
|
||||
ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
int parameterCount = method.getParameterTypes().length;
|
||||
for (int i = 0; i < parameterCount; i++) {
|
||||
MethodParameter methodParameter = new MethodParameter(method, i);
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.annotation.Header;
|
||||
import org.springframework.integration.annotation.Headers;
|
||||
import org.springframework.integration.gateway.GatewayMethodInboundMessageMapper;
|
||||
import org.springframework.integration.annotation.Payload;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
|
||||
/**
|
||||
@@ -192,7 +192,7 @@ public class GatewayMethodInboundMessageMapperToMessageTests {
|
||||
GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method);
|
||||
mapper.toMessage(new Object[] { "abc", "def" });
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void toMessageWithPayloadAndHeaders() throws Exception {
|
||||
Method method = TestService.class.getMethod("sendPayload", String.class);
|
||||
@@ -207,13 +207,65 @@ public class GatewayMethodInboundMessageMapperToMessageTests {
|
||||
assertEquals(42, message.getHeaders().get("bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMessageWithNonHeaderMapPayloadExpressionA() throws Exception {
|
||||
Method method = TestService.class.getMethod("sendNonHeadersMap", Map.class);
|
||||
Map<Integer, Object> map = new HashMap<Integer, Object>();
|
||||
map.put(1, "One");
|
||||
map.put(2, "Two");
|
||||
GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method);
|
||||
mapper.setPayloadExpression("'hello'");
|
||||
Message<?> message = mapper.toMessage(new Object[] { map });
|
||||
assertEquals("hello", message.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMessageWithNonHeaderMapPayloadExpressionB() throws Exception {
|
||||
Method method = TestService.class.getMethod("sendNonHeadersMap", Map.class);
|
||||
Map<Integer, Object> map = new HashMap<Integer, Object>();
|
||||
map.put(1, "One");
|
||||
map.put(2, "Two");
|
||||
GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method);
|
||||
mapper.setPayloadExpression("#args[0]");
|
||||
Message<?> message = mapper.toMessage(new Object[] { map });
|
||||
assertEquals(map, message.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMessageWithNonHeaderMapPayloadAnnotation() throws Exception {
|
||||
Method method = TestService.class.getMethod("sendNonHeadersMapWithPayloadAnnotation", Map.class);
|
||||
Map<Integer, Object> map = new HashMap<Integer, Object>();
|
||||
map.put(1, "One");
|
||||
map.put(2, "Two");
|
||||
GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method);
|
||||
Message<?> message = mapper.toMessage(new Object[] { map });
|
||||
assertEquals(map, message.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toMessageWithTwoMapsOneNonHeaderPayloadExpression() throws Exception {
|
||||
Method method = TestService.class.getMethod("sendNonHeadersMapFirstArgument", Map.class, Map.class);
|
||||
Map<Integer, Object> mapA = new HashMap<Integer, Object>();
|
||||
mapA.put(1, "One");
|
||||
mapA.put(2, "Two");
|
||||
Map<String, Object> mapB = new HashMap<String, Object>();
|
||||
mapB.put("1", "ONE");
|
||||
mapB.put("2", "TWO");
|
||||
GatewayMethodInboundMessageMapper mapper = new GatewayMethodInboundMessageMapper(method);
|
||||
mapper.setPayloadExpression("#args[0]");
|
||||
Message<?> message = mapper.toMessage(new Object[] { mapA, mapB });
|
||||
assertEquals(mapA, message.getPayload());
|
||||
assertEquals(mapB.get("1"), message.getHeaders().get("1"));
|
||||
assertEquals(mapB.get("2"), message.getHeaders().get("2"));
|
||||
}
|
||||
|
||||
|
||||
private static interface TestService {
|
||||
|
||||
void sendPayload(String payload);
|
||||
|
||||
void sendPayloadAndHeader(String payload, @Header("foo") String foo);
|
||||
|
||||
|
||||
void sendPayloadAndOptionalHeader(String payload, @Header(value="foo", required=false) String foo);
|
||||
|
||||
void sendPayloadAndHeadersMap(String payload, @Headers Map<String, Object> headers);
|
||||
@@ -230,6 +282,13 @@ public class GatewayMethodInboundMessageMapperToMessageTests {
|
||||
|
||||
void onlyHeaders(@Header("foo") String foo, @Header("bar") String bar);
|
||||
|
||||
void sendNonHeadersMap(Map<Integer, Object> map);
|
||||
|
||||
@Payload("#args[0]")
|
||||
void sendNonHeadersMapWithPayloadAnnotation(Map<Integer, Object> map);
|
||||
|
||||
void sendNonHeadersMapFirstArgument(Map<Integer, Object> mapA, Map<String, Object> mapB);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user