From 06286b19ce98a6610da59c560bf6e4742ecc8fa8 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Tue, 13 Oct 2009 14:20:24 +0000 Subject: [PATCH] Added URI variant methods to the RestTemplate. --- .../web/client/RestOperations.java | 82 ++++++++++++++++++- .../web/client/RestTemplate.java | 67 +++++++++++++-- .../client/RestTemplateIntegrationTests.java | 4 +- 3 files changed, 144 insertions(+), 9 deletions(-) diff --git a/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java b/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java index b67ffca9ac6..3f47d060af2 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java +++ b/org.springframework.web/src/main/java/org/springframework/web/client/RestOperations.java @@ -57,6 +57,15 @@ public interface RestOperations { */ T getForObject(String url, Class responseType, Map uriVariables) throws RestClientException; + /** + * Retrieve a representation by doing a GET on the URL . The response (if any) is converted and returned. + * + * @param url the URL + * @param responseType the type of the return value + * @return the converted object + */ + T getForObject(URI url, Class responseType) throws RestClientException; + // HEAD /** @@ -79,6 +88,14 @@ public interface RestOperations { */ HttpHeaders headForHeaders(String url, Map uriVariables) throws RestClientException; + /** + * Retrieve all headers of the resource specified by the URL. + * + * @param url the URL + * @return all HTTP headers of that resource + */ + HttpHeaders headForHeaders(URI url) throws RestClientException; + // POST /** @@ -88,6 +105,7 @@ public interface RestOperations { * * @param url the URL * @param request the Object to be POSTed, may be null + * @param uriVariables the variables to expand the template * @return the value for the Location header */ URI postForLocation(String url, Object request, String... uriVariables) throws RestClientException; @@ -104,12 +122,23 @@ public interface RestOperations { */ URI postForLocation(String url, Object request, Map uriVariables) throws RestClientException; + /** + * Create a new resource by POSTing the given object to the URL, and returns the value of the + * Location header. This header typically indicates where the new resource is stored. + * + * @param url the URL + * @param request the Object to be POSTed, may be null + * @return the value for the Location header + */ + URI postForLocation(URI url, Object request) throws RestClientException; + /** * Create a new resource by POSTing the given object to the URI template, and returns the representation * found in the response.

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 null + * @param uriVariables the variables to expand the template * @return the converted object */ T postForObject(String url, Object request, Class responseType, String... uriVariables) @@ -121,11 +150,22 @@ public interface RestOperations { * * @param url the URL * @param request the Object to be POSTed, may be null + * @param uriVariables the variables to expand the template * @return the converted object */ T postForObject(String url, Object request, Class responseType, Map uriVariables) throws RestClientException; + /** + * Create a new resource by POSTing the given object to the URL, and returns the representation + * found in the response. + * + * @param url the URL + * @param request the Object to be POSTed, may be null + * @return the converted object + */ + T postForObject(URI url, Object request, Class responseType) throws RestClientException; + // PUT /** @@ -148,6 +188,14 @@ public interface RestOperations { */ void put(String url, Object request, Map uriVariables) throws RestClientException; + /** + * Creates a new resource by PUTting the given object to URL. + * + * @param url the URL + * @param request the Object to be PUT, may be null + */ + void put(URI url, Object request) throws RestClientException; + // DELETE /** @@ -167,6 +215,13 @@ public interface RestOperations { */ void delete(String url, Map uriVariables) throws RestClientException; + /** + * Delete the resources at the specified URL. + * + * @param url the URL + */ + void delete(URI url) throws RestClientException; + // OPTIONS /** @@ -188,10 +243,18 @@ public interface RestOperations { */ Set optionsForAllow(String url, Map uriVariables) throws RestClientException; + /** + * Return the value of the Allow header for the given URL. + * + * @param url the URL + * @return the value of the allow header + */ + Set optionsForAllow(URI url) throws RestClientException; + // general execution /** - * Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, and reading the + * Execute the HTTP methods to the given URI template, preparing the request with the {@link RequestCallback}, and reading the * response with a {@link ResponseExtractor}.

URI Template variables are expanded using the given URI variables, if * any. * @@ -209,7 +272,7 @@ public interface RestOperations { String... uriVariables) throws RestClientException; /** - * Execute the HTTP methods to the given URI, preparing the request with the {@link RequestCallback}, and reading the + * Execute the HTTP methods to the given URI template, preparing the request with the {@link RequestCallback}, and reading the * response with a {@link ResponseExtractor}.

URI Template variables are expanded using the given URI variables * map. * @@ -226,4 +289,19 @@ public interface RestOperations { ResponseExtractor responseExtractor, Map uriVariables) throws RestClientException; + /** + * Execute the HTTP methods to the given URL, preparing the request with the {@link RequestCallback}, and reading the + * response with a {@link ResponseExtractor}. + * + * @param url the URL + * @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 + * @return an arbitrary object, as returned by the {@link ResponseExtractor} + */ + T execute(URI url, + HttpMethod method, + RequestCallback requestCallback, + ResponseExtractor responseExtractor) throws RestClientException; + } diff --git a/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java b/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java index 515869ffbf4..7210c05e365 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/org.springframework.web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -31,7 +31,6 @@ import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.support.HttpAccessor; -import org.springframework.http.converter.BufferedImageHttpMessageConverter; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; @@ -41,7 +40,7 @@ import org.springframework.util.Assert; import org.springframework.web.util.UriTemplate; /** - * The central class for client-side HTTP access.. It simplifies communication with HTTP servers, and + * The central class for client-side HTTP access. It simplifies communication with HTTP servers, and * enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible * template variables) and extract results. * @@ -55,9 +54,11 @@ import org.springframework.web.util.UriTemplate; * {@link #postForObject} * PUT{@link #put} any{@link #execute} * - *

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}. The string varargs variant expands the given template - * variables in order, so that + *

For each of these HTTP methods, there are three corresponding Java methods in the {@code RestTemplate}. + * Two variant take a {@code String} URI as first argument, and are capable of substituting any + * {@linkplain UriTemplate uri templates} in that URL using either a + * {@code String} variable arguments array, or a {@code Map}. The string varargs variant expands the + * given template variables in order, so that *

  * String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42",
  * "21");
@@ -70,6 +71,8 @@ import org.springframework.web.util.UriTemplate;
  * String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
  * 
* will perform a GET on {@code http://example.com/hotels/42/rooms/42}. + * Alternatively, there are {@link URI} variant methods, which do not allow for URI templates, but allow you to reuse a + * single, expanded URI multiple times. * *

Objects passed to and returned from these methods are converted to and from HTTP messages by {@link * HttpMessageConverter} instances. Converters for the main mime types are registered by default, but you can also write @@ -175,6 +178,13 @@ public class RestTemplate extends HttpAccessor implements RestOperations { new HttpMessageConverterExtractor(responseType, supportedMessageConverters), urlVariables); } + public T getForObject(URI url, Class responseType) throws RestClientException { + checkForSupportedMessageConverter(responseType); + List> supportedMessageConverters = getSupportedMessageConverters(responseType); + return execute(url, HttpMethod.GET, new AcceptHeaderRequestCallback(supportedMessageConverters), + new HttpMessageConverterExtractor(responseType, supportedMessageConverters)); + } + // HEAD public HttpHeaders headForHeaders(String url, String... urlVariables) throws RestClientException { @@ -185,6 +195,10 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return execute(url, HttpMethod.HEAD, null, this.headersExtractor, urlVariables); } + public HttpHeaders headForHeaders(URI url) throws RestClientException { + return execute(url, HttpMethod.HEAD, null, this.headersExtractor); + } + // POST public URI postForLocation(String url, Object request, String... urlVariables) throws RestClientException { @@ -206,6 +220,15 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return headers.getLocation(); } + public URI postForLocation(URI url, Object request) + throws RestClientException { + if (request != null) { + checkForSupportedMessageConverter(request.getClass()); + } + HttpHeaders headers = execute(url, HttpMethod.POST, new PostPutCallback(request), this.headersExtractor); + return headers.getLocation(); + } + public T postForObject(String url, Object request, Class responseType, String... uriVariables) throws RestClientException { if (request != null) { @@ -228,6 +251,16 @@ public class RestTemplate extends HttpAccessor implements RestOperations { new HttpMessageConverterExtractor(responseType, responseMessageConverters), uriVariables); } + public T postForObject(URI url, Object request, Class responseType) throws RestClientException { + if (request != null) { + checkForSupportedMessageConverter(request.getClass()); + } + checkForSupportedMessageConverter(responseType); + List> responseMessageConverters = getSupportedMessageConverters(responseType); + return execute(url, HttpMethod.POST, new PostPutCallback(request, responseMessageConverters), + new HttpMessageConverterExtractor(responseType, responseMessageConverters)); + } + // PUT public void put(String url, Object request, String... urlVariables) throws RestClientException { @@ -244,6 +277,13 @@ public class RestTemplate extends HttpAccessor implements RestOperations { execute(url, HttpMethod.PUT, new PostPutCallback(request), null, urlVariables); } + public void put(URI url, Object request) throws RestClientException { + if (request != null) { + checkForSupportedMessageConverter(request.getClass()); + } + execute(url, HttpMethod.PUT, new PostPutCallback(request), null); + } + // DELETE public void delete(String url, String... urlVariables) throws RestClientException { @@ -254,6 +294,10 @@ public class RestTemplate extends HttpAccessor implements RestOperations { execute(url, HttpMethod.DELETE, null, null, urlVariables); } + public void delete(URI url) throws RestClientException { + execute(url, HttpMethod.DELETE, null, null); + } + // OPTIONS public Set optionsForAllow(String url, String... urlVariables) throws RestClientException { @@ -268,6 +312,12 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return headers.getAllow(); } + public Set optionsForAllow(URI url) throws RestClientException { + + HttpHeaders headers = execute(url, HttpMethod.OPTIONS, null, this.headersExtractor); + return headers.getAllow(); + } + // general execution public T execute(String url, @@ -292,6 +342,13 @@ public class RestTemplate extends HttpAccessor implements RestOperations { return doExecute(expanded, method, requestCallback, responseExtractor); } + public T execute(URI url, + HttpMethod method, + RequestCallback requestCallback, + ResponseExtractor responseExtractor) throws RestClientException { + return doExecute(url, method, requestCallback, responseExtractor); + } + /** * Execute the given method on the provided URI. The {@link ClientHttpRequest} is processed using the {@link * RequestCallback}; the response with the {@link ResponseExtractor}. diff --git a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java index b4817898739..446249a9b64 100644 --- a/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java +++ b/org.springframework.web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java @@ -114,8 +114,8 @@ public class RestTemplateIntegrationTests { } @Test - public void optionsForAllow() { - Set allowed = template.optionsForAllow("http://localhost:8889/get"); + public void optionsForAllow() throws URISyntaxException { + Set allowed = template.optionsForAllow(new URI("http://localhost:8889/get")); assertEquals("Invalid response", EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE), allowed); }