diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallbackAdapter.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallbackAdapter.java deleted file mode 100644 index fae22dfc55..0000000000 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallbackAdapter.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2002-2013 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 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.web.client; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.client.AsyncClientHttpRequest; -import org.springframework.http.client.ClientHttpRequest; -import org.springframework.http.client.ClientHttpResponse; - -/** - * Adapts a {@link RequestCallback} to the {@link AsyncRequestCallback} interface. - * - * @author Arjen Poutsma - * @since 4.0 - */ -public class AsyncRequestCallbackAdapter implements AsyncRequestCallback { - - private final RequestCallback adaptee; - - /** - * Creates a new {@code AsyncRequestCallbackAdapter} from the given - * {@link RequestCallback}. - * - * @param requestCallback the callback to base this adapter on - */ - public AsyncRequestCallbackAdapter(RequestCallback requestCallback) { - this.adaptee = requestCallback; - } - - @Override - public void doWithRequest(final AsyncClientHttpRequest request) throws IOException { - if (adaptee != null) { - adaptee.doWithRequest(new ClientHttpRequest() { - @Override - public ClientHttpResponse execute() throws IOException { - throw new UnsupportedOperationException("execute not supported"); - } - - @Override - public OutputStream getBody() throws IOException { - return request.getBody(); - } - - @Override - public HttpMethod getMethod() { - return request.getMethod(); - } - - @Override - public URI getURI() { - return request.getURI(); - } - - @Override - public HttpHeaders getHeaders() { - return request.getHeaders(); - } - - }); - } - } -} diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java index c3a7861b6d..9abd6ea87b 100644 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java +++ b/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java @@ -42,6 +42,7 @@ public interface AsyncRestOperations { */ RestOperations getRestOperations(); + // GET /** @@ -272,6 +273,7 @@ public interface AsyncRestOperations { */ Future> optionsForAllow(URI url) throws RestClientException; + // exchange /** @@ -281,8 +283,8 @@ public interface AsyncRestOperations { *

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 wrapped in a {@link Future} @@ -298,8 +300,8 @@ public interface AsyncRestOperations { *

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 wrapped in a {@link Future} @@ -314,8 +316,8 @@ public interface AsyncRestOperations { * {@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 wrapped in a {@link Future} */ @@ -328,12 +330,10 @@ public interface AsyncRestOperations { * request entity to the request, and returns the response as {@link ResponseEntity}. * The given {@link ParameterizedTypeReference} is used to pass generic type * information: - * *

 	 * ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
 	 * ResponseEntity<List<MyBean>> response = template.exchange("http://example.com",HttpMethod.GET, null, myBean);
 	 * 
- * * @param url the URL * @param method the HTTP method (GET, POST, etc) * @param requestEntity the entity (headers and/or body) to write to the @@ -351,12 +351,10 @@ public interface AsyncRestOperations { * request entity to the request, and returns the response as {@link ResponseEntity}. * The given {@link ParameterizedTypeReference} is used to pass generic type * information: - * *
 	 * ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
 	 * ResponseEntity<List<MyBean>> response = template.exchange("http://example.com",HttpMethod.GET, null, myBean);
 	 * 
- * * @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} @@ -373,12 +371,10 @@ public interface AsyncRestOperations { * request entity to the request, and returns the response as {@link ResponseEntity}. * The given {@link ParameterizedTypeReference} is used to pass generic type * information: - * *
 	 * ParameterizedTypeReference<List<MyBean>> myBean = new ParameterizedTypeReference<List<MyBean>>() {};
 	 * ResponseEntity<List<MyBean>> response = template.exchange("http://example.com",HttpMethod.GET, null, myBean);
 	 * 
- * * @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} diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java index e3a9766815..731db4c088 100644 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java @@ -17,6 +17,7 @@ package org.springframework.web.client; import java.io.IOException; +import java.io.OutputStream; import java.lang.reflect.Type; import java.net.URI; import java.util.List; @@ -36,6 +37,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.http.client.AsyncClientHttpRequest; import org.springframework.http.client.AsyncClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.SimpleClientHttpRequestFactory; @@ -55,7 +57,7 @@ import org.springframework.web.util.UriTemplate; * {@linkplain #setMessageConverters(List) message converters} with this * {@code RestTemplate}. * - *

For more information, please refer to the {@link RestTemplate} API documentation

+ *

For more information, please refer to the {@link RestTemplate} API documentation. * * @author Arjen Poutsma * @since 4.0 @@ -82,7 +84,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * with the given {@code AsyncTaskExecutor} for asynchronous execution. */ public AsyncRestTemplate(AsyncTaskExecutor taskExecutor) { - Assert.notNull(taskExecutor, "'taskExecutor' must not be null"); + Assert.notNull(taskExecutor, "AsyncTaskExecutor must not be null"); SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setTaskExecutor(taskExecutor); this.syncTemplate = new RestTemplate(requestFactory); @@ -108,8 +110,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * @param asyncRequestFactory the asynchronous request factory * @param syncRequestFactory the synchronous request factory */ - public AsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory, - ClientHttpRequestFactory syncRequestFactory) { + public AsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory, ClientHttpRequestFactory syncRequestFactory) { this(asyncRequestFactory, new RestTemplate(syncRequestFactory)); } @@ -119,13 +120,13 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * @param requestFactory the asynchronous request factory to use * @param restTemplate the synchronous template to use */ - public AsyncRestTemplate(AsyncClientHttpRequestFactory requestFactory, - RestTemplate restTemplate) { + public AsyncRestTemplate(AsyncClientHttpRequestFactory requestFactory, RestTemplate restTemplate) { Assert.notNull(restTemplate, "'restTemplate' must not be null"); this.syncTemplate = restTemplate; setAsyncRequestFactory(requestFactory); } + /** * Set the error handler. *

By default, AsyncRestTemplate uses a @@ -160,11 +161,13 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe return syncTemplate.getMessageConverters(); } + // GET @Override - public Future> getForEntity(String url, Class responseType, - Object... uriVariables) throws RestClientException { + public Future> getForEntity(String url, Class responseType, Object... uriVariables) + throws RestClientException { + AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); @@ -173,14 +176,14 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe @Override public Future> getForEntity(String url, Class responseType, Map urlVariables) throws RestClientException { + AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables); } @Override - public Future> getForEntity(URI url, Class responseType) - throws RestClientException { + public Future> getForEntity(URI url, Class responseType) throws RestClientException { AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); return execute(url, HttpMethod.GET, requestCallback, responseExtractor); @@ -189,15 +192,13 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe // HEAD @Override - public Future headForHeaders(String url, Object... uriVariables) - throws RestClientException { + public Future headForHeaders(String url, Object... uriVariables) throws RestClientException { ResponseExtractor headersExtractor = headersExtractor(); return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); } @Override - public Future headForHeaders(String url, Map uriVariables) - throws RestClientException { + public Future headForHeaders(String url, Map uriVariables) throws RestClientException { ResponseExtractor headersExtractor = headersExtractor(); return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); } @@ -248,23 +249,19 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe public boolean cancel(boolean mayInterruptIfRunning) { return headersFuture.cancel(mayInterruptIfRunning); } - @Override public boolean isCancelled() { return headersFuture.isCancelled(); } - @Override public boolean isDone() { return headersFuture.isDone(); } - @Override public URI get() throws InterruptedException, ExecutionException { HttpHeaders headers = headersFuture.get(); return headers.getLocation(); } - @Override public URI get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { @@ -348,30 +345,23 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe // OPTIONS @Override - public Future> optionsForAllow(String url, Object... uriVariables) - throws RestClientException { + public Future> optionsForAllow(String url, Object... uriVariables) throws RestClientException { ResponseExtractor headersExtractor = headersExtractor(); - Future - headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, - uriVariables); + Future headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables); return extractAllowHeader(headersFuture); } @Override - public Future> optionsForAllow(String url, - Map uriVariables) throws RestClientException { + public Future> optionsForAllow(String url, Map uriVariables) throws RestClientException { ResponseExtractor headersExtractor = headersExtractor(); - Future - headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, - uriVariables); + Future headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables); return extractAllowHeader(headersFuture); } @Override public Future> optionsForAllow(URI url) throws RestClientException { ResponseExtractor headersExtractor = headersExtractor(); - Future - headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor); + Future headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor); return extractAllowHeader(headersFuture); } @@ -381,23 +371,19 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe public boolean cancel(boolean mayInterruptIfRunning) { return headersFuture.cancel(mayInterruptIfRunning); } - @Override public boolean isCancelled() { return headersFuture.isCancelled(); } - @Override public boolean isDone() { return headersFuture.isDone(); } - @Override public Set get() throws InterruptedException, ExecutionException { HttpHeaders headers = headersFuture.get(); return headers.getAllow(); } - @Override public Set get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { @@ -407,6 +393,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe }; } + // exchange @Override @@ -475,6 +462,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe return execute(url, method, requestCallback, responseExtractor); } + // general execution @Override @@ -496,8 +484,9 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } @Override - public Future execute(URI url, HttpMethod method, AsyncRequestCallback requestCallback, - ResponseExtractor responseExtractor) throws RestClientException { + public Future execute(URI url, HttpMethod method, + AsyncRequestCallback requestCallback, ResponseExtractor responseExtractor) + throws RestClientException { return doExecute(url, method, requestCallback, responseExtractor); } @@ -507,7 +496,6 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * {@link org.springframework.http.client.ClientHttpRequest} * is processed using the {@link RequestCallback}; the response with * the {@link ResponseExtractor}. - * * @param url the fully-expanded URL to connect to * @param method the HTTP method to execute (GET, POST, etc.) * @param requestCallback object that prepares the request (can be {@code null}) @@ -516,9 +504,8 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * @return an arbitrary object, as returned by the {@link ResponseExtractor} */ @SuppressWarnings("unchecked") - protected Future doExecute(URI url, HttpMethod method, - AsyncRequestCallback requestCallback, ResponseExtractor responseExtractor) - throws RestClientException { + protected Future doExecute(URI url, HttpMethod method, AsyncRequestCallback requestCallback, + ResponseExtractor responseExtractor) throws RestClientException { Assert.notNull(url, "'url' must not be null"); Assert.notNull(method, "'method' must not be null"); @@ -541,8 +528,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } } - private void logResponseStatus(HttpMethod method, URI url, - ClientHttpResponse response) { + private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse response) { if (logger.isDebugEnabled()) { try { logger.debug("Async " + method.name() + " request for \"" + url + @@ -555,8 +541,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } } - private void handleResponseError(HttpMethod method, URI url, - ClientHttpResponse response) throws IOException { + private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException { if (logger.isWarnEnabled()) { try { logger.warn("Async " + method.name() + " request for \"" + url + @@ -575,10 +560,8 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * headers based on the given response type and configured {@linkplain * #getMessageConverters() message converters}. */ - protected AsyncRequestCallbackAdapter acceptHeaderRequestCallback( - Class responseType) { - return new AsyncRequestCallbackAdapter( - this.syncTemplate.acceptHeaderRequestCallback(responseType)); + protected AsyncRequestCallback acceptHeaderRequestCallback(Class responseType) { + return new AsyncRequestCallbackAdapter(this.syncTemplate.acceptHeaderRequestCallback(responseType)); } /** @@ -586,25 +569,21 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe * request stream. */ protected AsyncRequestCallback httpEntityCallback(HttpEntity requestBody) { - return new AsyncRequestCallbackAdapter( - this.syncTemplate.httpEntityCallback(requestBody)); + return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(requestBody)); } /** * Returns a request callback implementation that writes the given object to the * request stream. */ - protected AsyncRequestCallback httpEntityCallback(HttpEntity request, - Type responseType) { - return new AsyncRequestCallbackAdapter( - this.syncTemplate.httpEntityCallback(request, responseType)); + protected AsyncRequestCallback httpEntityCallback(HttpEntity request, Type responseType) { + return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(request, responseType)); } /** * Returns a response extractor for {@link ResponseEntity}. */ - protected ResponseExtractor> responseEntityExtractor( - Type responseType) { + protected ResponseExtractor> responseEntityExtractor(Type responseType) { return this.syncTemplate.responseEntityExtractor(responseType); } @@ -615,6 +594,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe return this.syncTemplate.headersExtractor(); } + private abstract class ResponseFuture implements Future { private final HttpMethod method; @@ -623,7 +603,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe private final Future responseFuture; - protected ResponseFuture(HttpMethod method, URI url, Future responseFuture) { + public ResponseFuture(HttpMethod method, URI url, Future responseFuture) { this.method = method; this.url = url; this.responseFuture = responseFuture; @@ -650,8 +630,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } @Override - public T get(long timeout, TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { + public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return getInternal(this.responseFuture.get(timeout, unit)); } @@ -685,8 +664,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe private final ResponseExtractor responseExtractor; - private ResponseExtractorFuture(HttpMethod method, URI url, - Future responseFuture, + public ResponseExtractorFuture(HttpMethod method, URI url, Future responseFuture, ResponseExtractor responseExtractor) { super(method, url, responseFuture); this.responseExtractor = responseExtractor; @@ -698,10 +676,10 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } } + private class VoidResponseFuture extends ResponseFuture { - private VoidResponseFuture(HttpMethod method, URI url, - Future responseFuture) { + public VoidResponseFuture(HttpMethod method, URI url, Future responseFuture) { super(method, url, responseFuture); } @@ -712,4 +690,49 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe } + /** + * Adapts a {@link RequestCallback} to the {@link AsyncRequestCallback} interface. + */ + private static class AsyncRequestCallbackAdapter implements AsyncRequestCallback { + + private final RequestCallback adaptee; + + /** + * Create a new {@code AsyncRequestCallbackAdapter} from the given + * {@link RequestCallback}. + * @param requestCallback the callback to base this adapter on + */ + public AsyncRequestCallbackAdapter(RequestCallback requestCallback) { + this.adaptee = requestCallback; + } + + @Override + public void doWithRequest(final AsyncClientHttpRequest request) throws IOException { + if (this.adaptee != null) { + this.adaptee.doWithRequest(new ClientHttpRequest() { + @Override + public ClientHttpResponse execute() throws IOException { + throw new UnsupportedOperationException("execute not supported"); + } + @Override + public OutputStream getBody() throws IOException { + return request.getBody(); + } + @Override + public HttpMethod getMethod() { + return request.getMethod(); + } + @Override + public URI getURI() { + return request.getURI(); + } + @Override + public HttpHeaders getHeaders() { + return request.getHeaders(); + } + }); + } + } + } + }