Fix regression in MappingJackson2MessageConverter

As of 4.3.13 MappingJackson2MessageConverter uses the MethodParameter
hint to obtain generic type information but it needs to be careful, and
nest one level, if the target parameter type has a Message wrapper.

Issue: SPR-16486
This commit is contained in:
Rossen Stoyanchev
2018-02-12 21:30:26 -05:00
parent 3c631f8ea0
commit 4ee09c89b5
3 changed files with 55 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,7 +39,6 @@ import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
@@ -240,6 +239,9 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
if (conversionHint instanceof MethodParameter) {
MethodParameter param = (MethodParameter) conversionHint;
param = param.nestedIfOptional();
if (Message.class.isAssignableFrom(param.getParameterType())) {
param = param.nested();
}
Type genericParameterType = param.getNestedGenericParameterType();
Class<?> contextClass = param.getContainingClass();
Type type = GenericTypeResolver.resolveType(genericParameterType, contextClass);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* Test fixture for {@link org.springframework.messaging.converter.MappingJackson2MessageConverter}.
* Test fixture for {@link MappingJackson2MessageConverter}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
@@ -150,6 +150,20 @@ public class MappingJackson2MessageConverterTests {
assertEquals(Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L), actual);
}
@Test // SPR-16486
public void fromMessageToMessageWithPojo() throws Exception {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
String payload = "{\"string\":\"foo\"}";
Message<?> message = MessageBuilder.withPayload(payload.getBytes(StandardCharsets.UTF_8)).build();
Method method = getClass().getDeclaredMethod("handleMessage", Message.class);
MethodParameter param = new MethodParameter(method, 0);
Object actual = converter.fromMessage(message, Message.class, param);
assertTrue(actual instanceof MyBean);
assertEquals("foo", ((MyBean) actual).getString());
}
@Test
public void toMessage() throws Exception {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
@@ -242,6 +256,7 @@ public class MappingJackson2MessageConverterTests {
void handleList(List<Long> payload) {}
void handleMessage(Message<MyBean> message) {}
public static class MyBean {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.junit.rules.ExpectedException;
import org.springframework.core.MethodParameter;
import org.springframework.messaging.Message;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.support.ErrorMessage;
@@ -56,7 +57,7 @@ public class MessageMethodArgumentResolverTests {
@Before
public void setup() throws Exception {
this.method = MessageMethodArgumentResolverTests.class.getDeclaredMethod("handle",
Message.class, Message.class, Message.class, Message.class, ErrorMessage.class);
Message.class, Message.class, Message.class, Message.class, ErrorMessage.class, Message.class);
this.converter = mock(MessageConverter.class);
this.resolver = new MessageMethodArgumentResolver(this.converter);
@@ -222,6 +223,20 @@ public class MessageMethodArgumentResolverTests {
this.resolver.resolveArgument(parameter, message);
}
@Test // SPR-16486
public void resolveWithJacksonConverter() throws Exception {
Message<String> inMessage = MessageBuilder.withPayload("{\"foo\":\"bar\"}").build();
MethodParameter parameter = new MethodParameter(this.method, 5);
this.resolver = new MessageMethodArgumentResolver(new MappingJackson2MessageConverter());
Object actual = this.resolver.resolveArgument(parameter, inMessage);
assertTrue(actual instanceof Message);
Message<?> outMessage = (Message<?>) actual;
assertTrue(outMessage.getPayload() instanceof Foo);
assertEquals("bar", ((Foo) outMessage.getPayload()).getFoo());
}
@SuppressWarnings("unused")
private void handle(
@@ -229,7 +244,23 @@ public class MessageMethodArgumentResolverTests {
Message<Integer> integerPayload,
Message<Number> numberPayload,
Message<? extends Number> anyNumberPayload,
ErrorMessage subClass) {
ErrorMessage subClass,
Message<Foo> fooPayload) {
}
static class Foo {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
}