Allow to specify request body type in RestTemplate
This commit allows to specify the request body type in order to serialize generic types with a GenericHttpMessageConverter if needed. Issue: SPR-13154
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.http;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
@@ -54,6 +55,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* </pre>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.1
|
||||
* @see #getMethod()
|
||||
* @see #getUrl()
|
||||
@@ -64,6 +66,8 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
|
||||
private final URI url;
|
||||
|
||||
private final Type type;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor with method and URL but without body nor headers.
|
||||
@@ -81,7 +85,19 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
* @param url the URL
|
||||
*/
|
||||
public RequestEntity(T body, HttpMethod method, URI url) {
|
||||
this(body, null, method, url);
|
||||
this(body, null, method, url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with method, URL, body and type but without headers.
|
||||
* @param body the body
|
||||
* @param method the method
|
||||
* @param url the URL
|
||||
* @param type the type used for generic type resolution
|
||||
* @since 4.3
|
||||
*/
|
||||
public RequestEntity(T body, HttpMethod method, URI url, Type type) {
|
||||
this(body, null, method, url, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +107,7 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
* @param url the URL
|
||||
*/
|
||||
public RequestEntity(MultiValueMap<String, String> headers, HttpMethod method, URI url) {
|
||||
this(null, headers, method, url);
|
||||
this(null, headers, method, url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,9 +118,23 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
* @param url the URL
|
||||
*/
|
||||
public RequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url) {
|
||||
this(body, headers, method, url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with method, URL, headers, body and type.
|
||||
* @param body the body
|
||||
* @param headers the headers
|
||||
* @param method the method
|
||||
* @param url the URL
|
||||
* @param type the type used for generic type resolution
|
||||
* @since 4.3
|
||||
*/
|
||||
public RequestEntity(T body, MultiValueMap<String, String> headers, HttpMethod method, URI url, Type type) {
|
||||
super(body, headers);
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,6 +154,14 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of the request's body.
|
||||
* @return the request's body type
|
||||
* @since 4.3
|
||||
*/
|
||||
public Type getType() {
|
||||
return (this.type == null && this.getBody() != null ? this.getBody().getClass() : this.type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
@@ -327,6 +365,16 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
* @return the built request entity
|
||||
*/
|
||||
<T> RequestEntity<T> body(T body);
|
||||
|
||||
/**
|
||||
* Set the body and type of the request entity and build the RequestEntity.
|
||||
* @param <T> the type of the body
|
||||
* @param body the body of the request entity
|
||||
* @param type the type of the body, useful for generic type resolution
|
||||
* @return the built request entity
|
||||
* @since 4.3
|
||||
*/
|
||||
<T> RequestEntity<T> body(T body, Type type);
|
||||
}
|
||||
|
||||
|
||||
@@ -396,6 +444,11 @@ public class RequestEntity<T> extends HttpEntity<T> {
|
||||
public <T> RequestEntity<T> body(T body) {
|
||||
return new RequestEntity<T>(body, this.headers, this.method, this.url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RequestEntity<T> body(T body, Type type) {
|
||||
return new RequestEntity<T>(body, this.headers, this.method, this.url, type);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -782,11 +782,34 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
}
|
||||
else {
|
||||
Object requestBody = this.requestEntity.getBody();
|
||||
Class<?> requestType = requestBody.getClass();
|
||||
Class<?> requestBodyClass = requestBody.getClass();
|
||||
Type requestBodyType = (this.requestEntity instanceof RequestEntity ?
|
||||
((RequestEntity<?>)this.requestEntity).getType() : requestBodyClass);
|
||||
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
|
||||
MediaType requestContentType = requestHeaders.getContentType();
|
||||
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
|
||||
if (messageConverter.canWrite(requestType, requestContentType)) {
|
||||
if (messageConverter instanceof GenericHttpMessageConverter) {
|
||||
GenericHttpMessageConverter<Object> genericMessageConverter = (GenericHttpMessageConverter<Object>) messageConverter;
|
||||
if (genericMessageConverter.canWrite(requestBodyType, requestBodyClass, requestContentType)) {
|
||||
if (!requestHeaders.isEmpty()) {
|
||||
httpRequest.getHeaders().putAll(requestHeaders);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (requestContentType != null) {
|
||||
logger.debug("Writing [" + requestBody + "] as \"" + requestContentType +
|
||||
"\" using [" + messageConverter + "]");
|
||||
}
|
||||
else {
|
||||
logger.debug("Writing [" + requestBody + "] using [" + messageConverter + "]");
|
||||
}
|
||||
|
||||
}
|
||||
genericMessageConverter.write(
|
||||
requestBody, requestBodyType, requestContentType, httpRequest);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (messageConverter.canWrite(requestBodyClass, requestContentType)) {
|
||||
if (!requestHeaders.isEmpty()) {
|
||||
httpRequest.getHeaders().putAll(requestHeaders);
|
||||
}
|
||||
@@ -806,7 +829,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
}
|
||||
}
|
||||
String message = "Could not write request: no suitable HttpMessageConverter found for request type [" +
|
||||
requestType.getName() + "]";
|
||||
requestBodyClass.getName() + "]";
|
||||
if (requestContentType != null) {
|
||||
message += " and content type [" + requestContentType + "]";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user