From 70c166fbfdeafafa08a9445f191480ec4a75997d Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Mon, 13 Nov 2017 09:35:02 -0500 Subject: [PATCH] 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. --- .../util/MessagingMethodInvokerHelper.java | 37 +++++--- .../MethodInvokingMessageProcessorTests.java | 85 ++++++++++++++++++- 2 files changed, 108 insertions(+), 14 deletions(-) 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 abd7a5603e..076b9dc8cd 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 @@ -259,27 +259,38 @@ public class MessagingMethodInvokerHelper 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) { 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 5395216594..fd546af685 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 @@ -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; + + private final CountDownLatch latch = new CountDownLatch(1); + + @ServiceActivator(inputChannel = "foo") + @UseSpelInvoker + public void foo(Message 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. */