Fix issue with generic @RequestBody arguments
The original commit c9b7b1 ensured the ability to read parameterized type @RequestBody arguments via GenericHttpMessageConverter (e.g. application/json and List<String>). However, it also affected the ability to read @RequestBody arguments that happen are parameterized but aren't treated as such (e.g. application/x-www-form-urlencoded and MultiValueMap<String, String>). This commit corrects the issue. Issue: SPR-9570
This commit is contained in:
@@ -17,6 +17,9 @@
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -107,15 +110,15 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||
* @throws HttpMediaTypeNotSupportedException if no suitable message converter is found
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter methodParam,
|
||||
Type paramType) throws IOException, HttpMediaTypeNotSupportedException {
|
||||
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage,
|
||||
MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException {
|
||||
|
||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||
if (contentType == null) {
|
||||
contentType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
|
||||
Class<T> paramClass = (paramType instanceof Class) ? (Class) paramType : null;
|
||||
Class<T> paramClass = getParamClass(paramType);
|
||||
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
if (messageConverter instanceof GenericHttpMessageConverter) {
|
||||
@@ -142,6 +145,26 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
private Class getParamClass(Type paramType) {
|
||||
if (paramType instanceof Class) {
|
||||
return (Class) paramType;
|
||||
}
|
||||
else if (paramType instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) paramType).getGenericComponentType();
|
||||
if (componentType instanceof Class) {
|
||||
// Surely, there should be a nicer way to determine the array type
|
||||
return Array.newInstance((Class<?>) componentType, 0).getClass();
|
||||
}
|
||||
}
|
||||
else if (paramType instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) paramType;
|
||||
if (parameterizedType.getRawType() instanceof Class) {
|
||||
return (Class) parameterizedType.getRawType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link HttpInputMessage} from the given {@link NativeWebRequest}.
|
||||
*
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
@@ -89,23 +87,11 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
|
||||
Assert.isAssignable(HttpEntity.class, parameter.getParameterType());
|
||||
ParameterizedType type = (ParameterizedType) parameter.getGenericParameterType();
|
||||
if (type.getActualTypeArguments().length == 1) {
|
||||
Type typeArgument = type.getActualTypeArguments()[0];
|
||||
if (typeArgument instanceof Class) {
|
||||
return (Class<?>) typeArgument;
|
||||
}
|
||||
else if (typeArgument instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
|
||||
if (componentType instanceof Class) {
|
||||
// Surely, there should be a nicer way to determine the array type
|
||||
return Array.newInstance((Class<?>) componentType, 0).getClass();
|
||||
}
|
||||
}
|
||||
else if (typeArgument instanceof ParameterizedType) {
|
||||
return typeArgument;
|
||||
}
|
||||
return type.getActualTypeArguments()[0];
|
||||
}
|
||||
throw new IllegalArgumentException("HttpEntity parameter (" + parameter.getParameterName() + ") "
|
||||
+ "in method " + parameter.getMethod() + "is not parameterized");
|
||||
throw new IllegalArgumentException("HttpEntity parameter ("
|
||||
+ parameter.getParameterName() + ") in method " + parameter.getMethod()
|
||||
+ " is not parameterized or has more than one parameter");
|
||||
}
|
||||
|
||||
public void handleReturnValue(
|
||||
|
||||
Reference in New Issue
Block a user