SPR-5836 - RestTemplate - postForObject() method

This commit is contained in:
Arjen Poutsma 2009-06-19 07:50:06 +00:00
parent 4ea373b7dd
commit ddcd9f4905
4 changed files with 252 additions and 134 deletions

View File

@ -24,176 +24,203 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
/** /**
* Interface specifying a basic set of RESTful operations. * Interface specifying a basic set of RESTful operations. Implemented by {@link RestTemplate}. Not often used directly,
* Implemented by {@link RestTemplate}. Not often used directly, but a useful * but a useful option to enhance testability, as it can easily be mocked or stubbed.
* option to enhance testability, as it can easily be mocked or stubbed.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 3.0
* @see RestTemplate * @see RestTemplate
* @since 3.0
*/ */
public interface RestOperations { public interface RestOperations {
// GET // GET
/** /**
* Retrieve a representation by doing a GET on the specified URL. * Retrieve a representation by doing a GET on the specified URL. The response (if any) is converted and returned.
* <p>URI Template variables are expanded using the given URI variables, if any. * <p>URI Template variables are expanded using the given URI variables, if any.
* @param uri the URI *
* @param url the URL
* @param responseType the type of the return value * @param responseType the type of the return value
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
* @return the converted object * @return the converted object
*/ */
<T> T getForObject(String uri, Class<T> responseType, String... uriVariables) throws RestClientException; <T> T getForObject(String url, Class<T> responseType, String... uriVariables) throws RestClientException;
/** /**
* Retrieve a representation by doing a GET on the URI template. * Retrieve a representation by doing a GET on the URI template. The response (if any) is converted and returned.
* <p>URI Template variables are expanded using the given map. * <p>URI Template variables are expanded using the given map.
* @param uri the URI *
* @param url the URL
* @param responseType the type of the return value * @param responseType the type of the return value
* @param uriVariables the map containing variables for the URI template * @param uriVariables the map containing variables for the URI template
* @return the converted object * @return the converted object
*/ */
<T> T getForObject(String uri, Class<T> responseType, Map<String, String> uriVariables) throws RestClientException; <T> T getForObject(String url, Class<T> responseType, Map<String, String> uriVariables) throws RestClientException;
// HEAD // HEAD
/** /**
* Retrieve all headers of the resource specified by the URI template. * Retrieve all headers of the resource specified by the URI template. <p>URI Template variables are expanded using the
* <p>URI Template variables are expanded using the given URI variables, if any. * given URI variables, if any.
* @param uri the URI *
* @param url the URL
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
* @return all HTTP headers of that resource * @return all HTTP headers of that resource
*/ */
HttpHeaders headForHeaders(String uri, String... uriVariables) throws RestClientException; HttpHeaders headForHeaders(String url, String... uriVariables) throws RestClientException;
/** /**
* Retrieve all headers of the resource specified by the URI template. * Retrieve all headers of the resource specified by the URI template. <p>URI Template variables are expanded using the
* <p>URI Template variables are expanded using the given map. * given map.
* @param uri the URI *
* @param url the URL
* @param uriVariables the map containing variables for the URI template * @param uriVariables the map containing variables for the URI template
* @return all HTTP headers of that resource * @return all HTTP headers of that resource
*/ */
HttpHeaders headForHeaders(String uri, Map<String, String> uriVariables) throws RestClientException; HttpHeaders headForHeaders(String url, Map<String, String> uriVariables) throws RestClientException;
// POST // POST
/** /**
* Create a new resource by POSTing the given object to the URI template. The value of the <code>Location</code> * Create a new resource by POSTing the given object to the URI template, and returns the value of the
* header, indicating where the new resource is stored, is returned. * <code>Location</code> header. This header typically indicates where the new resource is stored. <p>URI Template
* <p>URI Template variables are expanded using the given URI variables, if any. * variables are expanded using the given URI variables, if any.
* @param uri the URI *
* @param url the URL
* @param request the Object to be POSTed, may be <code>null</code> * @param request the Object to be POSTed, may be <code>null</code>
* @return the value for the <code>Location</code> header * @return the value for the <code>Location</code> header
*/ */
URI postForLocation(String uri, Object request, String... uriVariables) throws RestClientException; URI postForLocation(String url, Object request, String... uriVariables) throws RestClientException;
/** /**
* Create a new resource by POSTing the given object to URI template. The value of the <code>Location</code> header, * Create a new resource by POSTing the given object to the URI template, and returns the value of the
* indicating where the new resource is stored, is returned. * <code>Location</code> header. This header typically indicates where the new resource is stored. <p>URI Template
* <p>URI Template variables are expanded using the given map. * variables are expanded using the given map.
* @param uri the URI *
* @param request the Object to be POSTed, may be <code>null</code> * @param url the URL
* @param request the Object to be POSTed, may be <code>null</code>
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
* @return the value for the <code>Location</code> header * @return the value for the <code>Location</code> header
*/ */
URI postForLocation(String uri, Object request, Map<String, String> uriVariables) throws RestClientException; URI postForLocation(String url, Object request, Map<String, String> uriVariables) throws RestClientException;
/**
* Create a new resource by POSTing the given object to the URI template, and returns the converted representation
* found in the response. <p>URI Template variables are expanded using the given URI variables, if any.
*
* @param url the URL
* @param request the Object to be POSTed, may be <code>null</code>
* @return the converted object
*/
<T> T postForObject(String url, Object request, Class<T> responseType, String... uriVariables)
throws RestClientException;
/**
* Create a new resource by POSTing the given object to the URI template, and returns the converted representation
* found in the response. <p>URI Template variables are expanded using the given map.
*
* @param url the URL
* @param request the Object to be POSTed, may be <code>null</code>
* @return the converted object
*/
<T> T postForObject(String url, Object request, Class<T> responseType, Map<String, String> uriVariables)
throws RestClientException;
// PUT // PUT
/** /**
* Create or update a resource by PUTting the given object to the URI. * Create or update a resource by PUTting the given object to the URI. <p>URI Template variables are expanded using the
* <p>URI Template variables are expanded using the given URI variables, if any. * given URI variables, if any.
* @param uri the URI *
* @param request the Object to be PUT, may be <code>null</code> * @param url the URL
* @param request the Object to be PUT, may be <code>null</code>
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
*/ */
void put(String uri, Object request, String... uriVariables) throws RestClientException; void put(String url, Object request, String... uriVariables) throws RestClientException;
/** /**
* Creates a new resource by PUTting the given object to URI template. * Creates a new resource by PUTting the given object to URI template. <p>URI Template variables are expanded using the
* <p>URI Template variables are expanded using the given map. * given map.
* @param uri the URI *
* @param request the Object to be PUT, may be <code>null</code> * @param url the URL
* @param request the Object to be PUT, may be <code>null</code>
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
*/ */
void put(String uri, Object request, Map<String, String> uriVariables) throws RestClientException; void put(String url, Object request, Map<String, String> uriVariables) throws RestClientException;
// DELETE // DELETE
/** /**
* Delete the resources at the specified URI. * Delete the resources at the specified URI. <p>URI Template variables are expanded using the given URI variables, if
* <p>URI Template variables are expanded using the given URI variables, if any. * any.
* @param uri the URI *
* @param url the URL
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
*/ */
void delete(String uri, String... uriVariables) throws RestClientException; void delete(String url, String... uriVariables) throws RestClientException;
/** /**
* Delete the resources at the specified URI. * Delete the resources at the specified URI. <p>URI Template variables are expanded using the given map.
* <p>URI Template variables are expanded using the given map. *
* @param uri the URI * @param url the URL
* @param uriVariables the variables to expand the template * @param uriVariables the variables to expand the template
*/ */
void delete(String uri, Map<String, String> uriVariables) throws RestClientException; void delete(String url, Map<String, String> uriVariables) throws RestClientException;
// OPTIONS // OPTIONS
/** /**
* Return the value of the Allow header for the given URI. * Return the value of the Allow header for the given URI. <p>URI Template variables are expanded using the given URI
* <p>URI Template variables are expanded using the given URI variables, if any. * variables, if any.
* @param uri the URI *
* @param url the URL
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return the value of the allow header * @return the value of the allow header
*/ */
Set<HttpMethod> optionsForAllow(String uri, String... uriVariables) throws RestClientException; Set<HttpMethod> optionsForAllow(String url, String... uriVariables) throws RestClientException;
/** /**
* Return the value of the Allow header for the given URI. * Return the value of the Allow header for the given URI. <p>URI Template variables are expanded using the given map.
* <p>URI Template variables are expanded using the given map. *
* @param uri the URI * @param url the URL
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return the value of the allow header * @return the value of the allow header
*/ */
Set<HttpMethod> optionsForAllow(String uri, Map<String, String> uriVariables) throws RestClientException; Set<HttpMethod> optionsForAllow(String url, Map<String, String> uriVariables) throws RestClientException;
// general execution // general execution
/** /**
* Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, * Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, and reading the
* and reading the response with a {@link ResponseExtractor}. * response with a {@link ResponseExtractor}. <p>URI Template variables are expanded using the given URI variables, if
* <p>URI Template variables are expanded using the given URI variables, if any. * any.
* @param uri the URI *
* @param method the HTTP method (GET, POST, etc) * @param url the URL
* @param requestCallback object that prepares the request * @param method the HTTP method (GET, POST, etc)
* @param requestCallback object that prepares the request
* @param responseExtractor object that extracts the return value from the response * @param responseExtractor object that extracts the return value from the response
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return an arbitrary object, as returned by the {@link ResponseExtractor} * @return an arbitrary object, as returned by the {@link ResponseExtractor}
*/ */
<T> T execute(String uri, <T> T execute(String url,
HttpMethod method, HttpMethod method,
RequestCallback requestCallback, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, ResponseExtractor<T> responseExtractor,
String... uriVariables) throws RestClientException; String... uriVariables) throws RestClientException;
/** /**
* Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, * Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, and reading the
* and reading the response with a {@link ResponseExtractor}. * response with a {@link ResponseExtractor}. <p>URI Template variables are expanded using the given URI variables
* <p>URI Template variables are expanded using the given URI variables map. * map.
* @param uri the URI *
* @param method the HTTP method (GET, POST, etc) * @param url the URL
* @param requestCallback object that prepares the request * @param method the HTTP method (GET, POST, etc)
* @param requestCallback object that prepares the request
* @param responseExtractor object that extracts the return value from the response * @param responseExtractor object that extracts the return value from the response
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return an arbitrary object, as returned by the {@link ResponseExtractor} * @return an arbitrary object, as returned by the {@link ResponseExtractor}
*/ */
<T> T execute(String uri, <T> T execute(String url,
HttpMethod method, HttpMethod method,
RequestCallback requestCallback, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, ResponseExtractor<T> responseExtractor,

View File

@ -45,27 +45,22 @@ import org.springframework.web.util.UriTemplate;
* enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible * enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible
* template variables) and extract results. * template variables) and extract results.
* *
* <p>The main entry points of this template are the methods named after the six main HTTP methods: * <p>The main entry points of this template are the methods named after the six main HTTP methods: <table> <tr><th>HTTP
* <table> * method</th><th>RestTemplate methods</th></tr> <tr><td>DELETE</td><td>{@link #delete}</td></tr>
* <tr><th>HTTP method</th><th>RestTemplate methods</th></tr> * <tr><td>GET</td><td>{@link #getForObject}</td></tr> <tr><td>HEAD</td><td>{@link #headForHeaders}</td></tr>
* <tr><td>DELETE</td><td>{@link #delete}</td></tr> * <tr><td>OPTIONS</td><td>{@link #optionsForAllow}</td></tr> <tr><td>POST</td><td>{@link #postForLocation}</td></tr>
* <tr><td>GET</td><td>{@link #getForObject}</td></tr> * <tr><td>PUT</td><td>{@link #put}</td></tr> <tr><td>any</td><td>{@link #execute}</td></tr> </table>
* <tr><td>HEAD</td><td>{@link #headForHeaders}</td></tr>
* <tr><td>OPTIONS</td><td>{@link #optionsForAllow}</td></tr>
* <tr><td>POST</td><td>{@link #postForLocation}</td></tr>
* <tr><td>PUT</td><td>{@link #put}</td></tr>
* <tr><td>any</td><td>{@link #execute}</td></tr>
* </table>
* *
* <p>Each of these methods takes {@linkplain UriTemplate uri template} arguments in two forms: as a {@code String} * <p>Each of these methods takes {@linkplain UriTemplate uri template} arguments in two forms: as a {@code String}
* variable arguments array, or as a {@code Map<String, String>}. The string varargs variant expands the given template * variable arguments array, or as a {@code Map<String, String>}. The string varargs variant expands the given template
* variables in order, so that * variables in order, so that
* <pre> * <pre>
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21"); * String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42",
* "21");
* </pre> * </pre>
* will perform a GET on {@code http://example.com/hotels/42/bookings/21}. The map variant expands the template * will perform a GET on {@code http://example.com/hotels/42/bookings/21}. The map variant expands the template based on
* based on variable name, and is therefore more useful when using many variables, or when a single variable is used * variable name, and is therefore more useful when using many variables, or when a single variable is used multiple
* multiple times. For example: * times. For example:
* <pre> * <pre>
* Map&lt;String, String&gt; vars = Collections.singletonMap("hotel", "42"); * Map&lt;String, String&gt; vars = Collections.singletonMap("hotel", "42");
* String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars); * String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
@ -78,9 +73,9 @@ import org.springframework.web.util.UriTemplate;
* bean property. * bean property.
* *
* <p>This template uses a {@link org.springframework.http.client.SimpleClientHttpRequestFactory} and a {@link * <p>This template uses a {@link org.springframework.http.client.SimpleClientHttpRequestFactory} and a {@link
* DefaultResponseErrorHandler} as default strategies for creating HTTP connections or handling HTTP errors, respectively. * DefaultResponseErrorHandler} as default strategies for creating HTTP connections or handling HTTP errors,
* These defaults can be overridden through the {@link #setRequestFactory(ClientHttpRequestFactory) requestFactory} and * respectively. These defaults can be overridden through the {@link #setRequestFactory(ClientHttpRequestFactory)
* {@link #setErrorHandler(ResponseErrorHandler) errorHandler} bean properties. * requestFactory} and {@link #setErrorHandler(ResponseErrorHandler) errorHandler} bean properties.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @see HttpMessageConverter * @see HttpMessageConverter
@ -116,18 +111,15 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
} }
/** /**
* Set the message body converters to use. These converters are used to convert * Set the message body converters to use. These converters are used to convert from and to HTTP requests and
* from and to HTTP requests and responses. * responses.
*/ */
public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) { public void setMessageConverters(HttpMessageConverter<?>[] messageConverters) {
Assert.notEmpty(messageConverters, "'messageConverters' must not be empty"); Assert.notEmpty(messageConverters, "'messageConverters' must not be empty");
this.messageConverters = messageConverters; this.messageConverters = messageConverters;
} }
/** /** Returns the message body converters. These converters are used to convert from and to HTTP requests and responses. */
* Returns the message body converters. These converters are used to convert
* from and to HTTP requests and responses.
*/
public HttpMessageConverter<?>[] getMessageConverters() { public HttpMessageConverter<?>[] getMessageConverters() {
return this.messageConverters; return this.messageConverters;
} }
@ -167,7 +159,7 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
checkForSupportedMessageConverter(responseType); checkForSupportedMessageConverter(responseType);
List<HttpMessageConverter<T>> supportedMessageConverters = getSupportedMessageConverters(responseType); List<HttpMessageConverter<T>> supportedMessageConverters = getSupportedMessageConverters(responseType);
return execute(url, HttpMethod.GET, new GetCallback<T>(supportedMessageConverters), return execute(url, HttpMethod.GET, new AcceptHeaderRequestCallback<T>(supportedMessageConverters),
new HttpMessageConverterExtractor<T>(responseType, supportedMessageConverters), urlVariables); new HttpMessageConverterExtractor<T>(responseType, supportedMessageConverters), urlVariables);
} }
@ -176,7 +168,7 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
checkForSupportedMessageConverter(responseType); checkForSupportedMessageConverter(responseType);
List<HttpMessageConverter<T>> supportedMessageConverters = getSupportedMessageConverters(responseType); List<HttpMessageConverter<T>> supportedMessageConverters = getSupportedMessageConverters(responseType);
return execute(url, HttpMethod.GET, new GetCallback<T>(supportedMessageConverters), return execute(url, HttpMethod.GET, new AcceptHeaderRequestCallback<T>(supportedMessageConverters),
new HttpMessageConverterExtractor<T>(responseType, supportedMessageConverters), urlVariables); new HttpMessageConverterExtractor<T>(responseType, supportedMessageConverters), urlVariables);
} }
@ -211,6 +203,28 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
return headers.getLocation(); return headers.getLocation();
} }
public <T> T postForObject(String url, Object request, Class<T> responseType, String... uriVariables)
throws RestClientException {
if (request != null) {
checkForSupportedMessageConverter(request.getClass());
}
checkForSupportedMessageConverter(responseType);
List<HttpMessageConverter<T>> responseMessageConverters = getSupportedMessageConverters(responseType);
return execute(url, HttpMethod.POST, new PostPutCallback<T>(request, responseMessageConverters),
new HttpMessageConverterExtractor<T>(responseType, responseMessageConverters), uriVariables);
}
public <T> T postForObject(String url, Object request, Class<T> responseType, Map<String, String> uriVariables)
throws RestClientException {
if (request != null) {
checkForSupportedMessageConverter(request.getClass());
}
checkForSupportedMessageConverter(responseType);
List<HttpMessageConverter<T>> responseMessageConverters = getSupportedMessageConverters(responseType);
return execute(url, HttpMethod.POST, new PostPutCallback<T>(request, responseMessageConverters),
new HttpMessageConverterExtractor<T>(responseType, responseMessageConverters), uriVariables);
}
// PUT // PUT
public void put(String url, Object request, String... urlVariables) throws RestClientException { public void put(String url, Object request, String... urlVariables) throws RestClientException {
@ -337,11 +351,11 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
} }
/** Request callback implementation that prepares the request's accept headers. */ /** Request callback implementation that prepares the request's accept headers. */
private class GetCallback<T> implements RequestCallback { private class AcceptHeaderRequestCallback<T> implements RequestCallback {
private final List<HttpMessageConverter<T>> messageConverters; private final List<HttpMessageConverter<T>> messageConverters;
private GetCallback(List<HttpMessageConverter<T>> messageConverters) { private AcceptHeaderRequestCallback(List<HttpMessageConverter<T>> messageConverters) {
this.messageConverters = messageConverters; this.messageConverters = messageConverters;
} }
@ -357,22 +371,32 @@ public class RestTemplate extends HttpAccessor implements RestOperations {
allSupportedMediaTypes.add(supportedMediaType); allSupportedMediaTypes.add(supportedMediaType);
} }
} }
Collections.sort(allSupportedMediaTypes); if (!allSupportedMediaTypes.isEmpty()) {
request.getHeaders().setAccept(allSupportedMediaTypes); Collections.sort(allSupportedMediaTypes);
request.getHeaders().setAccept(allSupportedMediaTypes);
}
} }
} }
/** Request callback implementation that writes the given object to the request stream. */ /** Request callback implementation that writes the given object to the request stream. */
private class PostPutCallback implements RequestCallback { private class PostPutCallback<T> extends AcceptHeaderRequestCallback<T> {
private final Object request; private final Object request;
private PostPutCallback(Object request) { private PostPutCallback(Object request, List<HttpMessageConverter<T>> responseMessageConverters) {
super(responseMessageConverters);
this.request = request; this.request = request;
} }
private PostPutCallback(Object request) {
super(Collections.<HttpMessageConverter<T>>emptyList());
this.request = request;
}
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException { public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
super.doWithRequest(httpRequest);
if (request != null) { if (request != null) {
HttpMessageConverter entityConverter = getSupportedMessageConverters(this.request.getClass()).get(0); HttpMessageConverter entityConverter = getSupportedMessageConverters(this.request.getClass()).get(0);
entityConverter.write(this.request, httpRequest); entityConverter.write(this.request, httpRequest);

View File

@ -42,24 +42,26 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.client.CommonsClientHttpRequestFactory; import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
/** /** @author Arjen Poutsma */
* @author Arjen Poutsma
*/
public class RestTemplateIntegrationTests { public class RestTemplateIntegrationTests {
private RestTemplate template; private RestTemplate template;
private static Server jettyServer; private static Server jettyServer;
private static String helloWorld = "H\u00e9llo W\u00f6rld";
@BeforeClass @BeforeClass
public static void startJettyServer() throws Exception { public static void startJettyServer() throws Exception {
jettyServer = new Server(8889); jettyServer = new Server(8889);
Context jettyContext = new Context(jettyServer, "/"); Context jettyContext = new Context(jettyServer, "/");
String s = "H\u00e9llo W\u00f6rld"; byte[] bytes = helloWorld.getBytes("UTF-8");
byte[] bytes = s.getBytes("UTF-8"); String contentType = "text/plain;charset=utf-8";
jettyContext.addServlet(new ServletHolder(new GetServlet(bytes, "text/plain;charset=utf-8")), "/get"); jettyContext.addServlet(new ServletHolder(new GetServlet(bytes, contentType)), "/get");
jettyContext jettyContext.addServlet(new ServletHolder(new GetServlet(new byte[0], contentType)), "/get/nothing");
.addServlet(new ServletHolder(new PostServlet(s, new URI("http://localhost:8889/post/1"))), "/post"); jettyContext.addServlet(
new ServletHolder(new PostServlet(helloWorld, "http://localhost:8889/post/1", bytes, contentType)),
"/post");
jettyContext.addServlet(new ServletHolder(new ErrorServlet(404)), "/errors/notfound"); jettyContext.addServlet(new ServletHolder(new ErrorServlet(404)), "/errors/notfound");
jettyContext.addServlet(new ServletHolder(new ErrorServlet(500)), "/errors/server"); jettyContext.addServlet(new ServletHolder(new ErrorServlet(500)), "/errors/server");
jettyServer.start(); jettyServer.start();
@ -67,7 +69,6 @@ public class RestTemplateIntegrationTests {
@Before @Before
public void createTemplate() { public void createTemplate() {
// template = new RestTemplate();
template = new RestTemplate(new CommonsClientHttpRequestFactory()); template = new RestTemplate(new CommonsClientHttpRequestFactory());
} }
@ -81,15 +82,27 @@ public class RestTemplateIntegrationTests {
@Test @Test
public void getString() { public void getString() {
String s = template.getForObject("http://localhost:8889/{method}", String.class, "get"); String s = template.getForObject("http://localhost:8889/{method}", String.class, "get");
assertEquals("Invalid content", "H\u00e9llo W\u00f6rld", s); assertEquals("Invalid content", helloWorld, s);
} }
@Test @Test
public void postString() throws URISyntaxException { public void getNoResponse() {
URI location = template.postForLocation("http://localhost:8889/{method}", "H\u00e9llo W\u00f6rld", "post"); String s = template.getForObject("http://localhost:8889/get/nothing", String.class);
assertEquals("Invalid content", "", s);
}
@Test
public void postForLocation() throws URISyntaxException {
URI location = template.postForLocation("http://localhost:8889/{method}", helloWorld, "post");
assertEquals("Invalid location", new URI("http://localhost:8889/post/1"), location); assertEquals("Invalid location", new URI("http://localhost:8889/post/1"), location);
} }
@Test
public void postForObject() throws URISyntaxException {
String s = template.postForObject("http://localhost:8889/{method}", helloWorld, String.class, "post");
assertEquals("Invalid content", helloWorld, s);
}
@Test(expected = HttpClientErrorException.class) @Test(expected = HttpClientErrorException.class)
public void notFound() { public void notFound() {
template.execute("http://localhost:8889/errors/notfound", HttpMethod.GET, null, null); template.execute("http://localhost:8889/errors/notfound", HttpMethod.GET, null, null);
@ -107,10 +120,7 @@ public class RestTemplateIntegrationTests {
EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE), allowed); EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE), allowed);
} }
/** Servlet that returns and error message for a given status code. */
/**
* Servlet that returns and error message for a given status code.
*/
private static class ErrorServlet extends GenericServlet { private static class ErrorServlet extends GenericServlet {
private final int sc; private final int sc;
@ -125,7 +135,6 @@ public class RestTemplateIntegrationTests {
} }
} }
private static class GetServlet extends HttpServlet { private static class GetServlet extends HttpServlet {
private final byte[] buf; private final byte[] buf;
@ -140,22 +149,27 @@ public class RestTemplateIntegrationTests {
@Override @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { throws ServletException, IOException {
response.setContentLength(buf.length);
response.setContentType(contentType); response.setContentType(contentType);
response.setContentLength(buf.length);
FileCopyUtils.copy(buf, response.getOutputStream()); FileCopyUtils.copy(buf, response.getOutputStream());
} }
} }
private static class PostServlet extends HttpServlet { private static class PostServlet extends HttpServlet {
private final String s; private final String s;
private final URI location; private final String location;
private PostServlet(String s, URI location) { private final byte[] buf;
private final String contentType;
private PostServlet(String s, String location, byte[] buf, String contentType) {
this.s = s; this.s = s;
this.location = location; this.location = location;
this.buf = buf;
this.contentType = contentType;
} }
@Override @Override
@ -166,7 +180,10 @@ public class RestTemplateIntegrationTests {
String body = FileCopyUtils.copyToString(request.getReader()); String body = FileCopyUtils.copyToString(request.getReader());
assertEquals("Invalid request body", s, body); assertEquals("Invalid request body", s, body);
response.setStatus(HttpServletResponse.SC_CREATED); response.setStatus(HttpServletResponse.SC_CREATED);
response.setHeader("Location", location.toASCIIString()); response.setHeader("Location", location);
response.setContentLength(buf.length);
response.setContentType(contentType);
FileCopyUtils.copy(buf, response.getOutputStream());
} }
} }

View File

@ -40,9 +40,7 @@ import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
/** /** @author Arjen Poutsma */
* @author Arjen Poutsma
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class RestTemplateTests { public class RestTemplateTests {
@ -265,7 +263,7 @@ public class RestTemplateTests {
} }
@Test @Test
public void postNull() throws Exception { public void postForLocationNull() throws Exception {
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request); expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
HttpHeaders requestHeaders = new HttpHeaders(); HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders); expect(request.getHeaders()).andReturn(requestHeaders);
@ -282,6 +280,58 @@ public class RestTemplateTests {
verifyMocks(); verifyMocks();
} }
@Test
public void postForObject() throws Exception {
expect(converter.supports(String.class)).andReturn(true).times(2);
expect(converter.supports(Integer.class)).andReturn(true).times(2);
MediaType textPlain = new MediaType("text", "plain");
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain)).times(2);
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(this.request);
HttpHeaders requestHeaders = new HttpHeaders();
expect(this.request.getHeaders()).andReturn(requestHeaders);
String request = "Hello World";
converter.write(request, this.request);
expect(this.request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(textPlain);
expect(response.getHeaders()).andReturn(responseHeaders);
Integer expected = 42;
expect(converter.read(Integer.class, response)).andReturn(expected);
response.close();
replayMocks();
Integer result = template.postForObject("http://example.com", request, Integer.class);
assertEquals("Invalid POST result", expected, result);
assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept"));
verifyMocks();
}
@Test
public void postForObjectNull() throws Exception {
expect(converter.supports(Integer.class)).andReturn(true).times(2);
MediaType textPlain = new MediaType("text", "plain");
expect(converter.getSupportedMediaTypes()).andReturn(Collections.singletonList(textPlain)).times(2);
expect(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.POST)).andReturn(request);
HttpHeaders requestHeaders = new HttpHeaders();
expect(request.getHeaders()).andReturn(requestHeaders).times(2);
expect(request.execute()).andReturn(response);
expect(errorHandler.hasError(response)).andReturn(false);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(textPlain);
expect(response.getHeaders()).andReturn(responseHeaders);
expect(converter.read(Integer.class, response)).andReturn(null);
response.close();
replayMocks();
template.postForObject("http://example.com", null, Integer.class);
assertEquals("Invalid content length", 0, requestHeaders.getContentLength());
verifyMocks();
}
@Test @Test
public void put() throws Exception { public void put() throws Exception {
expect(converter.supports(String.class)).andReturn(true).times(2); expect(converter.supports(String.class)).andReturn(true).times(2);