mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 16:39:29 +00:00
RestTemplate provides patchForObject operations
Issue: SPR-14857
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -28,9 +28,9 @@ import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
/**
|
||||
* Interface specifying a basic set of RESTful operations. Implemented by {@link RestTemplate}.
|
||||
* Not often used directly, but a useful option to enhance testability, as it can easily
|
||||
* be mocked or stubbed.
|
||||
* Interface specifying a basic set of RESTful operations.
|
||||
* Implemented by {@link RestTemplate}. Not often used directly, but a useful
|
||||
* option to enhance testability, as it can easily be mocked or stubbed.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
@@ -139,13 +139,13 @@ public interface RestOperations {
|
||||
// POST
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* {@code Location} header. This header typically indicates where the new resource is stored.
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of
|
||||
* the {@code Location} header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the {@code Location} header
|
||||
* @see HttpEntity
|
||||
@@ -153,13 +153,13 @@ public interface RestOperations {
|
||||
URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException;
|
||||
|
||||
/**
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of the
|
||||
* {@code Location} header. This header typically indicates where the new resource is stored.
|
||||
* Create a new resource by POSTing the given object to the URI template, and returns the value of
|
||||
* the {@code Location} header. This header typically indicates where the new resource is stored.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the value for the {@code Location} header
|
||||
* @see HttpEntity
|
||||
@@ -172,7 +172,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @return the value for the {@code Location} header
|
||||
* @see HttpEntity
|
||||
*/
|
||||
@@ -185,7 +185,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
@@ -201,7 +201,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
@@ -216,7 +216,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
@@ -230,11 +230,11 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
|
||||
throws RestClientException;
|
||||
@@ -246,11 +246,11 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
|
||||
throws RestClientException;
|
||||
@@ -261,10 +261,10 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be POSTed, may be {@code null}
|
||||
* @param request the Object to be POSTed (may be {@code null})
|
||||
* @return the converted object
|
||||
* @see HttpEntity
|
||||
* @since 3.0.2
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
|
||||
|
||||
@@ -277,7 +277,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be {@code null}
|
||||
* @param request the Object to be PUT (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
@@ -289,7 +289,7 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be {@code null}
|
||||
* @param request the Object to be PUT (may be {@code null})
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @see HttpEntity
|
||||
*/
|
||||
@@ -300,12 +300,64 @@ public interface RestOperations {
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PUT, may be {@code null}
|
||||
* @param request the Object to be PUT (may be {@code null})
|
||||
* @see HttpEntity
|
||||
*/
|
||||
void put(URI url, Object request) throws RestClientException;
|
||||
|
||||
|
||||
// PATCH
|
||||
|
||||
/**
|
||||
* Update a resource by PATCHing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PATCHed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @since 4.3.5
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
|
||||
throws RestClientException;
|
||||
|
||||
/**
|
||||
* Update a resource by PATCHing the given object to the URI template,
|
||||
* and returns the representation found in the response.
|
||||
* <p>URI Template variables are expanded using the given map.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PATCHed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand the template
|
||||
* @return the converted object
|
||||
* @since 4.3.5
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
|
||||
throws RestClientException;
|
||||
|
||||
/**
|
||||
* Update a resource by PATCHing the given object to the URL,
|
||||
* and returns the representation found in the response.
|
||||
* <p>The {@code request} parameter can be a {@link HttpEntity} in order to
|
||||
* add additional HTTP headers to the request.
|
||||
* @param url the URL
|
||||
* @param request the Object to be PATCHed (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @return the converted object
|
||||
* @since 4.3.5
|
||||
* @see HttpEntity
|
||||
*/
|
||||
<T> T patchForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
|
||||
|
||||
|
||||
|
||||
// DELETE
|
||||
|
||||
/**
|
||||
@@ -368,7 +420,8 @@ public interface RestOperations {
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request
|
||||
* may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
@@ -383,7 +436,8 @@ public interface RestOperations {
|
||||
* <p>URI Template variables are expanded using the given URI variables, if any.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request
|
||||
* (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
@@ -397,7 +451,8 @@ public interface RestOperations {
|
||||
* returns the response as {@link ResponseEntity}.
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request
|
||||
* (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity
|
||||
* @since 3.0.2
|
||||
@@ -416,7 +471,7 @@ public interface RestOperations {
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the
|
||||
* request, may be {@code null}
|
||||
* request (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
@@ -435,7 +490,8 @@ public interface RestOperations {
|
||||
* </pre>
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request
|
||||
* (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @param uriVariables the variables to expand in the template
|
||||
* @return the response as entity
|
||||
@@ -454,7 +510,8 @@ public interface RestOperations {
|
||||
* </pre>
|
||||
* @param url the URL
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request, may be {@code null}
|
||||
* @param requestEntity the entity (headers and/or body) to write to the request
|
||||
* (may be {@code null})
|
||||
* @param responseType the type of the return value
|
||||
* @return the response as entity
|
||||
* @since 3.2
|
||||
|
||||
@@ -445,6 +445,39 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
}
|
||||
|
||||
|
||||
// PATCH
|
||||
|
||||
@Override
|
||||
public <T> T patchForObject(String url, Object request, Class<T> responseType,
|
||||
Object... uriVariables) throws RestClientException {
|
||||
|
||||
RequestCallback requestCallback = httpEntityCallback(request, responseType);
|
||||
HttpMessageConverterExtractor<T> responseExtractor =
|
||||
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
|
||||
return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T patchForObject(String url, Object request, Class<T> responseType,
|
||||
Map<String, ?> uriVariables) throws RestClientException {
|
||||
|
||||
RequestCallback requestCallback = httpEntityCallback(request, responseType);
|
||||
HttpMessageConverterExtractor<T> responseExtractor =
|
||||
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
|
||||
return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor, uriVariables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T patchForObject(URI url, Object request, Class<T> responseType)
|
||||
throws RestClientException {
|
||||
|
||||
RequestCallback requestCallback = httpEntityCallback(request, responseType);
|
||||
HttpMessageConverterExtractor<T> responseExtractor =
|
||||
new HttpMessageConverterExtractor<T>(responseType, getMessageConverters());
|
||||
return execute(url, HttpMethod.PATCH, requestCallback, responseExtractor);
|
||||
}
|
||||
|
||||
|
||||
// DELETE
|
||||
|
||||
@Override
|
||||
@@ -647,8 +680,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
* @param method the HTTP method to execute (GET, POST, etc.)
|
||||
* @param response the resulting {@link ClientHttpResponse}
|
||||
* @throws IOException if propagated from {@link ResponseErrorHandler}
|
||||
* @see #setErrorHandler
|
||||
* @since 4.1.6
|
||||
* @see #setErrorHandler
|
||||
*/
|
||||
protected void handleResponse(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
|
||||
ResponseErrorHandler errorHandler = getErrorHandler();
|
||||
|
||||
+9
@@ -154,6 +154,15 @@ public class RestTemplateIntegrationTests extends AbstractMockWebServerTestCase
|
||||
assertEquals("Invalid content", helloWorld, s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchForObject() throws URISyntaxException {
|
||||
// JDK client does not support the PATCH method
|
||||
Assume.assumeThat(this.clientHttpRequestFactory,
|
||||
Matchers.not(Matchers.instanceOf(SimpleClientHttpRequestFactory.class)));
|
||||
String s = template.patchForObject(baseUrl + "/{method}", helloWorld, String.class, "patch");
|
||||
assertEquals("Invalid content", helloWorld, s);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notFound() {
|
||||
try {
|
||||
|
||||
@@ -67,6 +67,7 @@ public class RestTemplateTests {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private HttpMessageConverter converter;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
requestFactory = mock(ClientHttpRequestFactory.class);
|
||||
@@ -79,6 +80,7 @@ public class RestTemplateTests {
|
||||
template.setErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void varArgsTemplateVariables() throws Exception {
|
||||
given(requestFactory.createRequest(new URI("http://example.com/hotels/42/bookings/21"), HttpMethod.GET))
|
||||
@@ -590,6 +592,69 @@ public class RestTemplateTests {
|
||||
verify(response).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchForObject() throws Exception {
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
given(converter.canRead(Integer.class, null)).willReturn(true);
|
||||
given(converter.getSupportedMediaTypes()).willReturn(Collections.singletonList(textPlain));
|
||||
given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.PATCH)).willReturn(this.request);
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
given(this.request.getHeaders()).willReturn(requestHeaders);
|
||||
String request = "Hello World";
|
||||
given(converter.canWrite(String.class, null)).willReturn(true);
|
||||
converter.write(request, null, this.request);
|
||||
given(this.request.execute()).willReturn(response);
|
||||
given(errorHandler.hasError(response)).willReturn(false);
|
||||
Integer expected = 42;
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentType(textPlain);
|
||||
responseHeaders.setContentLength(10);
|
||||
given(response.getStatusCode()).willReturn(HttpStatus.OK);
|
||||
given(response.getHeaders()).willReturn(responseHeaders);
|
||||
given(response.getBody()).willReturn(new ByteArrayInputStream(expected.toString().getBytes()));
|
||||
given(converter.canRead(Integer.class, textPlain)).willReturn(true);
|
||||
given(converter.read(eq(Integer.class), any(HttpInputMessage.class))).willReturn(expected);
|
||||
HttpStatus status = HttpStatus.OK;
|
||||
given(response.getStatusCode()).willReturn(status);
|
||||
given(response.getStatusText()).willReturn(status.getReasonPhrase());
|
||||
|
||||
Integer result = template.patchForObject("http://example.com", request, Integer.class);
|
||||
assertEquals("Invalid POST result", expected, result);
|
||||
assertEquals("Invalid Accept header", textPlain.toString(), requestHeaders.getFirst("Accept"));
|
||||
|
||||
verify(response).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void patchForObjectNull() throws Exception {
|
||||
MediaType textPlain = new MediaType("text", "plain");
|
||||
given(converter.canRead(Integer.class, null)).willReturn(true);
|
||||
given(converter.getSupportedMediaTypes()).willReturn(Collections.singletonList(textPlain));
|
||||
given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.PATCH)).willReturn(request);
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
given(request.getHeaders()).willReturn(requestHeaders);
|
||||
given(request.execute()).willReturn(response);
|
||||
given(errorHandler.hasError(response)).willReturn(false);
|
||||
HttpHeaders responseHeaders = new HttpHeaders();
|
||||
responseHeaders.setContentType(textPlain);
|
||||
responseHeaders.setContentLength(10);
|
||||
given(response.getStatusCode()).willReturn(HttpStatus.OK);
|
||||
given(response.getHeaders()).willReturn(responseHeaders);
|
||||
given(converter.canRead(Integer.class, textPlain)).willReturn(true);
|
||||
given(converter.read(Integer.class, response)).willReturn(null);
|
||||
HttpStatus status = HttpStatus.OK;
|
||||
given(response.getStatusCode()).willReturn(status);
|
||||
given(response.getStatusText()).willReturn(status.getReasonPhrase());
|
||||
|
||||
Integer result = template.patchForObject("http://example.com", null, Integer.class);
|
||||
assertNull("Invalid POST result", result);
|
||||
assertEquals("Invalid content length", 0, requestHeaders.getContentLength());
|
||||
|
||||
verify(response).close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void delete() throws Exception {
|
||||
given(requestFactory.createRequest(new URI("http://example.com"), HttpMethod.DELETE)).willReturn(request);
|
||||
@@ -730,4 +795,5 @@ public class RestTemplateTests {
|
||||
|
||||
verify(response).close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user