INT-4362: MMIH Catch Conversion Exception

JIRA: https://jira.spring.io/browse/INT-4362

INT-4312 added a JSON conversion when there is a single method with a non-String parameter.

Add more tests for parameters of type `Message`.

Catch conversion exceptions and use the message as-is if the conversion fails.
This commit is contained in:
Gary Russell
2017-11-13 09:35:02 -05:00
committed by Artem Bilan
parent 4207f36a17
commit 70c166fbfd
2 changed files with 108 additions and 14 deletions

View File

@@ -259,27 +259,38 @@ public class MessagingMethodInvokerHelper<T> extends AbstractExpressionEvaluator
@SuppressWarnings("unchecked")
public T process(Message<?> message) throws Exception {
Message<?> messageToProcess = message;
/*
* 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.
*/
Message<?> messageToProcess = possiblyConvert(message);
ParametersWrapper parameters = new ParametersWrapper(messageToProcess);
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)) {
messageToProcess = getMessageBuilderFactory()
.withPayload(this.jsonObjectMapper.fromJson(message.getPayload(), type))
.copyHeaders(message.getHeaders())
.build();
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);
}
}
}
}
ParametersWrapper parameters = new ParametersWrapper(messageToProcess);
return processInternal(parameters);
return message;
}
private boolean contentTypeIsJson(Message<?> message) {

View File

@@ -877,7 +877,8 @@ public class MethodInvokingMessageProcessorTests {
public void testSingleMethodJson() throws Exception {
SingleMethodJsonWithSpELBean bean = new SingleMethodJsonWithSpELBean();
MessagingMethodInvokerHelper<?> helper = new MessagingMethodInvokerHelper<>(bean,
SingleMethodJsonWithSpELBean.class.getDeclaredMethod("foo", SingleMethodJsonWithSpELBean.Foo.class),
SingleMethodJsonWithSpELBean.class.getDeclaredMethod("foo",
SingleMethodJsonWithSpELBean.Foo.class),
false);
Message<?> message = new GenericMessage<>("{\"bar\":\"bar\"}",
Collections.singletonMap(MessageHeaders.CONTENT_TYPE, "application/json"));
@@ -885,6 +886,39 @@ public class MethodInvokingMessageProcessorTests {
assertThat(bean.foo.bar, equalTo("bar"));
}
@Test
public void testSingleMethodBadJson() throws Exception {
SingleMethodJsonWithSpELMessageWildBean bean = new SingleMethodJsonWithSpELMessageWildBean();
MessagingMethodInvokerHelper<?> helper = new MessagingMethodInvokerHelper<>(bean,
SingleMethodJsonWithSpELMessageWildBean.class.getDeclaredMethod("foo", Message.class), false);
Message<?> message = new GenericMessage<>("baz",
Collections.singletonMap(MessageHeaders.CONTENT_TYPE, "application/json"));
helper.process(message);
assertThat(bean.foo.getPayload(), equalTo("baz"));
}
@Test
public void testSingleMethodJsonMessageFoo() throws Exception {
SingleMethodJsonWithSpELMessageFooBean bean = new SingleMethodJsonWithSpELMessageFooBean();
MessagingMethodInvokerHelper<?> helper = new MessagingMethodInvokerHelper<>(bean,
SingleMethodJsonWithSpELMessageFooBean.class.getDeclaredMethod("foo", Message.class), false);
Message<?> message = new GenericMessage<>("{\"bar\":\"bar\"}",
Collections.singletonMap(MessageHeaders.CONTENT_TYPE, "application/json"));
helper.process(message);
assertThat(bean.foo.getPayload().bar, equalTo("bar"));
}
@Test
public void testSingleMethodJsonMessageWild() throws Exception {
SingleMethodJsonWithSpELMessageWildBean bean = new SingleMethodJsonWithSpELMessageWildBean();
MessagingMethodInvokerHelper<?> helper = new MessagingMethodInvokerHelper<>(bean,
SingleMethodJsonWithSpELMessageWildBean.class.getDeclaredMethod("foo", Message.class), false);
Message<?> message = new GenericMessage<>("{\"bar\":\"baz\"}",
Collections.singletonMap(MessageHeaders.CONTENT_TYPE, "application/json"));
helper.process(message);
assertThat(bean.foo.getPayload(), instanceOf(Map.class));
assertThat(((Map<?, ?>) bean.foo.getPayload()).get("bar"), equalTo("baz"));
}
@Test
public void testCompiledSpELForProxy() {
@@ -1236,6 +1270,55 @@ public class MethodInvokingMessageProcessorTests {
}
public static class SingleMethodJsonWithSpELMessageFooBean {
private Message<Foo> foo;
private final CountDownLatch latch = new CountDownLatch(1);
@ServiceActivator(inputChannel = "foo")
@UseSpelInvoker
public void foo(Message<Foo> foo) {
this.foo = foo;
this.latch.countDown();
}
public static class Foo {
private String bar;
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
@Override
public String toString() {
return "Foo [bar=" + this.bar + "]";
}
}
}
public static class SingleMethodJsonWithSpELMessageWildBean {
private Message<?> foo;
private final CountDownLatch latch = new CountDownLatch(1);
@ServiceActivator(inputChannel = "foo")
@UseSpelInvoker
public void foo(Message<?> foo) {
this.foo = foo;
this.latch.countDown();
}
}
/*
* Public for SpEL access.
*/