diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java b/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java index 4735861db2..2e2462d3ac 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/MessagingMethodInvokerHelper.java @@ -308,46 +308,10 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator } public T process(Message message) throws Exception { - Message messageToProcess = possiblyConvert(message); - ParametersWrapper parameters = new ParametersWrapper(messageToProcess); + ParametersWrapper parameters = new ParametersWrapper(message); return processInternal(parameters); } - /* - * If there's a single method, the content is JSON, the payload is a - * String or byte[], the parameter doesn't match the payload, - * and there is a Json Object Mapper on the CP, - * convert. - */ - private Message possiblyConvert(Message message) throws Exception { - if (this.handlerMethod != null && this.handlerMethod.getTargetParameterType() != null && - this.jsonObjectMapper != null) { - Class type = this.handlerMethod.getTargetParameterType(); - if ((message.getPayload() instanceof String && !type.equals(String.class) - || message.getPayload() instanceof byte[] && !type.equals(byte[].class)) - && contentTypeIsJson(message)) { - - try { - return getMessageBuilderFactory() - .withPayload(this.jsonObjectMapper.fromJson(message.getPayload(), type)) - .copyHeaders(message.getHeaders()) - .build(); - } - catch (Exception e) { - if (logger.isDebugEnabled()) { - logger.debug("Failed to convert from JSON", e); - } - } - } - } - return message; - } - - private boolean contentTypeIsJson(Message message) { - Object contentType = message.getHeaders().get(MessageHeaders.CONTENT_TYPE); - return contentType != null && contentType.toString().contains("json"); - } - public T process(Collection> messages, Map headers) throws Exception { ParametersWrapper parameters = new ParametersWrapper(messages, headers); return processInternal(parameters); @@ -645,6 +609,8 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator @SuppressWarnings("unchecked") private T invokeExpression(Expression expression, ParametersWrapper parameters) throws Exception { try { + + convertJsonPayloadIfNecessary(parameters); return (T) evaluateExpression(expression, parameters); } catch (Exception e) { @@ -662,6 +628,52 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator } } + /* + * If there's a single method, it is SpEL only, the content is JSON, + * the payload is a String or byte[], the parameter doesn't match the payload, + * and there is a Json Object Mapper on the CP, convert. + */ + private void convertJsonPayloadIfNecessary(ParametersWrapper parameters) { + if (parameters.message != null && + this.handlerMethod != null && + this.handlerMethod.exclusiveMethodParameter != null && + this.jsonObjectMapper != null) { + + Class type = this.handlerMethod.targetParameterType; + if ((parameters.getPayload() instanceof String && !type.equals(String.class) + || parameters.getPayload() instanceof byte[] && !type.equals(byte[].class)) + && contentTypeIsJson(parameters.message)) { + + try { + Object targetPayload = this.jsonObjectMapper.fromJson(parameters.getPayload(), type); + + if (this.handlerMethod.targetParameterTypeDescriptor.isAssignableTo(messageTypeDescriptor)) { + parameters.message = + getMessageBuilderFactory() + .withPayload(targetPayload) + .copyHeaders(parameters.getHeaders()) + .build(); + } + else { + parameters.payload = targetPayload; + } + + + } + catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Failed to convert from JSON", e); + } + } + } + } + } + + private boolean contentTypeIsJson(Message message) { + Object contentType = message.getHeaders().get(MessageHeaders.CONTENT_TYPE); + return contentType != null && contentType.toString().contains("json"); + } + private Map, HandlerMethod>> findHandlerMethodsForTarget(final Object targetObject, final Class annotationType, final String methodName, final boolean requiresReply) { @@ -1013,6 +1025,8 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator private volatile Class targetParameterType = Void.class; + private MethodParameter exclusiveMethodParameter; + private volatile boolean messageMethod; private volatile boolean spelOnly; @@ -1220,6 +1234,7 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator private void setExclusiveTargetParameterType(TypeDescriptor targetParameterType, MethodParameter methodParameter) { + if (this.targetParameterTypeDescriptor != null) { throw new IneligibleMethodException("Found more than one parameter type candidate: [" + this.targetParameterTypeDescriptor + "] and [" + targetParameterType + "]"); @@ -1233,18 +1248,20 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator else { this.targetParameterType = targetParameterType.getObjectType(); } + + this.exclusiveMethodParameter = methodParameter; } } public static class ParametersWrapper { - private final Object payload; - private final Collection> messages; private final Map headers; - private final Message message; + private Message message; + + private Object payload; ParametersWrapper(Message message) { this.message = message; @@ -1254,10 +1271,8 @@ public class MessagingMethodInvokerHelper extends AbstractExpressionEvaluator } ParametersWrapper(Collection> messages, Map headers) { - this.payload = null; this.messages = messages; this.headers = headers; - this.message = null; } /** diff --git a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java index b6925af60b..c3654dd7eb 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/handler/MethodInvokingMessageProcessorTests.java @@ -1017,7 +1017,12 @@ public class MethodInvokingMessageProcessorTests { ObjectMapper objectMapper = new ObjectMapper(); byte[] value = objectMapper.writeValueAsBytes(testData); - String result = (String) processor.processMessage(new GenericMessage<>(value)); + Message testMessage = + MessageBuilder.withPayload(value) + .setHeader(MessageHeaders.CONTENT_TYPE, "application/json") + .build(); + + String result = (String) processor.processMessage(testMessage); assertEquals("Foo,Bar", result); }