Turned AsyncRequestCallbackAdapter into a private inner class

Issue: SPR-8804
This commit is contained in:
Juergen Hoeller 2013-08-28 12:56:18 +02:00
parent bb971cecf1
commit 38c8c6d085
3 changed files with 94 additions and 156 deletions

View File

@ -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();
}
});
}
}
}

View File

@ -42,6 +42,7 @@ public interface AsyncRestOperations {
*/ */
RestOperations getRestOperations(); RestOperations getRestOperations();
// GET // GET
/** /**
@ -272,6 +273,7 @@ public interface AsyncRestOperations {
*/ */
Future<Set<HttpMethod>> optionsForAllow(URI url) throws RestClientException; Future<Set<HttpMethod>> optionsForAllow(URI url) throws RestClientException;
// exchange // exchange
/** /**
@ -281,8 +283,8 @@ public interface AsyncRestOperations {
* <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 url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param requestEntity the entity (headers and/or body) to write to the request, may * @param requestEntity the entity (headers and/or body) to write to the request
* be {@code null} * (may be {@code null})
* @param responseType the type of the return value * @param responseType the type of the return value
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return the response as entity wrapped in a {@link Future} * @return the response as entity wrapped in a {@link Future}
@ -298,8 +300,8 @@ public interface AsyncRestOperations {
* <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 url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param requestEntity the entity (headers and/or body) to write to the request, may * @param requestEntity the entity (headers and/or body) to write to the request
* be {@code null} * (may be {@code null})
* @param responseType the type of the return value * @param responseType the type of the return value
* @param uriVariables the variables to expand in the template * @param uriVariables the variables to expand in the template
* @return the response as entity wrapped in a {@link Future} * @return the response as entity wrapped in a {@link Future}
@ -314,8 +316,8 @@ public interface AsyncRestOperations {
* {@link ResponseEntity}. * {@link ResponseEntity}.
* @param url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param requestEntity the entity (headers and/or body) to write to the request, may * @param requestEntity the entity (headers and/or body) to write to the request
* be {@code null} * (may be {@code null})
* @param responseType the type of the return value * @param responseType the type of the return value
* @return the response as entity wrapped in a {@link Future} * @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}. * request entity to the request, and returns the response as {@link ResponseEntity}.
* The given {@link ParameterizedTypeReference} is used to pass generic type * The given {@link ParameterizedTypeReference} is used to pass generic type
* information: * information:
*
* <pre class="code"> * <pre class="code">
* ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {}; * ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {};
* ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean); * ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean);
* </pre> * </pre>
*
* @param url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param requestEntity the entity (headers and/or body) to write to the * @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}. * request entity to the request, and returns the response as {@link ResponseEntity}.
* The given {@link ParameterizedTypeReference} is used to pass generic type * The given {@link ParameterizedTypeReference} is used to pass generic type
* information: * information:
*
* <pre class="code"> * <pre class="code">
* ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {}; * ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {};
* ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean); * ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean);
* </pre> * </pre>
*
* @param url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @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}
@ -373,12 +371,10 @@ public interface AsyncRestOperations {
* request entity to the request, and returns the response as {@link ResponseEntity}. * request entity to the request, and returns the response as {@link ResponseEntity}.
* The given {@link ParameterizedTypeReference} is used to pass generic type * The given {@link ParameterizedTypeReference} is used to pass generic type
* information: * information:
*
* <pre class="code"> * <pre class="code">
* ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {}; * ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt; myBean = new ParameterizedTypeReference&lt;List&lt;MyBean&gt;&gt;() {};
* ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean); * ResponseEntity&lt;List&lt;MyBean&gt;&gt; response = template.exchange(&quot;http://example.com&quot;,HttpMethod.GET, null, myBean);
* </pre> * </pre>
*
* @param url the URL * @param url the URL
* @param method the HTTP method (GET, POST, etc) * @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}

View File

@ -17,6 +17,7 @@
package org.springframework.web.client; package org.springframework.web.client;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
@ -36,6 +37,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.client.AsyncClientHttpRequest; import org.springframework.http.client.AsyncClientHttpRequest;
import org.springframework.http.client.AsyncClientHttpRequestFactory; import org.springframework.http.client.AsyncClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.http.client.SimpleClientHttpRequestFactory;
@ -55,7 +57,7 @@ import org.springframework.web.util.UriTemplate;
* {@linkplain #setMessageConverters(List) message converters} with this * {@linkplain #setMessageConverters(List) message converters} with this
* {@code RestTemplate}. * {@code RestTemplate}.
* *
* <p>For more information, please refer to the {@link RestTemplate} API documentation</p> * <p>For more information, please refer to the {@link RestTemplate} API documentation.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 4.0 * @since 4.0
@ -82,7 +84,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
* with the given {@code AsyncTaskExecutor} for asynchronous execution. * with the given {@code AsyncTaskExecutor} for asynchronous execution.
*/ */
public AsyncRestTemplate(AsyncTaskExecutor taskExecutor) { public AsyncRestTemplate(AsyncTaskExecutor taskExecutor) {
Assert.notNull(taskExecutor, "'taskExecutor' must not be null"); Assert.notNull(taskExecutor, "AsyncTaskExecutor must not be null");
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setTaskExecutor(taskExecutor); requestFactory.setTaskExecutor(taskExecutor);
this.syncTemplate = new RestTemplate(requestFactory); this.syncTemplate = new RestTemplate(requestFactory);
@ -108,8 +110,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
* @param asyncRequestFactory the asynchronous request factory * @param asyncRequestFactory the asynchronous request factory
* @param syncRequestFactory the synchronous request factory * @param syncRequestFactory the synchronous request factory
*/ */
public AsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory, public AsyncRestTemplate(AsyncClientHttpRequestFactory asyncRequestFactory, ClientHttpRequestFactory syncRequestFactory) {
ClientHttpRequestFactory syncRequestFactory) {
this(asyncRequestFactory, new RestTemplate(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 requestFactory the asynchronous request factory to use
* @param restTemplate the synchronous template to use * @param restTemplate the synchronous template to use
*/ */
public AsyncRestTemplate(AsyncClientHttpRequestFactory requestFactory, public AsyncRestTemplate(AsyncClientHttpRequestFactory requestFactory, RestTemplate restTemplate) {
RestTemplate restTemplate) {
Assert.notNull(restTemplate, "'restTemplate' must not be null"); Assert.notNull(restTemplate, "'restTemplate' must not be null");
this.syncTemplate = restTemplate; this.syncTemplate = restTemplate;
setAsyncRequestFactory(requestFactory); setAsyncRequestFactory(requestFactory);
} }
/** /**
* Set the error handler. * Set the error handler.
* <p>By default, AsyncRestTemplate uses a * <p>By default, AsyncRestTemplate uses a
@ -160,11 +161,13 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
return syncTemplate.getMessageConverters(); return syncTemplate.getMessageConverters();
} }
// GET // GET
@Override @Override
public <T> Future<ResponseEntity<T>> getForEntity(String url, Class<T> responseType, public <T> Future<ResponseEntity<T>> getForEntity(String url, Class<T> responseType, Object... uriVariables)
Object... uriVariables) throws RestClientException { throws RestClientException {
AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
@ -173,14 +176,14 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
@Override @Override
public <T> Future<ResponseEntity<T>> getForEntity(String url, Class<T> responseType, public <T> Future<ResponseEntity<T>> getForEntity(String url, Class<T> responseType,
Map<String, ?> urlVariables) throws RestClientException { Map<String, ?> urlVariables) throws RestClientException {
AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
} }
@Override @Override
public <T> Future<ResponseEntity<T>> getForEntity(URI url, Class<T> responseType) public <T> Future<ResponseEntity<T>> getForEntity(URI url, Class<T> responseType) throws RestClientException {
throws RestClientException {
AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType); ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor); return execute(url, HttpMethod.GET, requestCallback, responseExtractor);
@ -189,15 +192,13 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
// HEAD // HEAD
@Override @Override
public Future<HttpHeaders> headForHeaders(String url, Object... uriVariables) public Future<HttpHeaders> headForHeaders(String url, Object... uriVariables) throws RestClientException {
throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor(); ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables);
} }
@Override @Override
public Future<HttpHeaders> headForHeaders(String url, Map<String, ?> uriVariables) public Future<HttpHeaders> headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException {
throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor(); ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables);
} }
@ -248,23 +249,19 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
public boolean cancel(boolean mayInterruptIfRunning) { public boolean cancel(boolean mayInterruptIfRunning) {
return headersFuture.cancel(mayInterruptIfRunning); return headersFuture.cancel(mayInterruptIfRunning);
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
return headersFuture.isCancelled(); return headersFuture.isCancelled();
} }
@Override @Override
public boolean isDone() { public boolean isDone() {
return headersFuture.isDone(); return headersFuture.isDone();
} }
@Override @Override
public URI get() throws InterruptedException, ExecutionException { public URI get() throws InterruptedException, ExecutionException {
HttpHeaders headers = headersFuture.get(); HttpHeaders headers = headersFuture.get();
return headers.getLocation(); return headers.getLocation();
} }
@Override @Override
public URI get(long timeout, TimeUnit unit) public URI get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
@ -348,30 +345,23 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
// OPTIONS // OPTIONS
@Override @Override
public Future<Set<HttpMethod>> optionsForAllow(String url, Object... uriVariables) public Future<Set<HttpMethod>> optionsForAllow(String url, Object... uriVariables) throws RestClientException {
throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor(); ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
Future<HttpHeaders> Future<HttpHeaders> headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables);
headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor,
uriVariables);
return extractAllowHeader(headersFuture); return extractAllowHeader(headersFuture);
} }
@Override @Override
public Future<Set<HttpMethod>> optionsForAllow(String url, public Future<Set<HttpMethod>> optionsForAllow(String url, Map<String, ?> uriVariables) throws RestClientException {
Map<String, ?> uriVariables) throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor(); ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
Future<HttpHeaders> Future<HttpHeaders> headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor, uriVariables);
headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor,
uriVariables);
return extractAllowHeader(headersFuture); return extractAllowHeader(headersFuture);
} }
@Override @Override
public Future<Set<HttpMethod>> optionsForAllow(URI url) throws RestClientException { public Future<Set<HttpMethod>> optionsForAllow(URI url) throws RestClientException {
ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor(); ResponseExtractor<HttpHeaders> headersExtractor = headersExtractor();
Future<HttpHeaders> Future<HttpHeaders> headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor);
headersFuture = execute(url, HttpMethod.OPTIONS, null, headersExtractor);
return extractAllowHeader(headersFuture); return extractAllowHeader(headersFuture);
} }
@ -381,23 +371,19 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
public boolean cancel(boolean mayInterruptIfRunning) { public boolean cancel(boolean mayInterruptIfRunning) {
return headersFuture.cancel(mayInterruptIfRunning); return headersFuture.cancel(mayInterruptIfRunning);
} }
@Override @Override
public boolean isCancelled() { public boolean isCancelled() {
return headersFuture.isCancelled(); return headersFuture.isCancelled();
} }
@Override @Override
public boolean isDone() { public boolean isDone() {
return headersFuture.isDone(); return headersFuture.isDone();
} }
@Override @Override
public Set<HttpMethod> get() throws InterruptedException, ExecutionException { public Set<HttpMethod> get() throws InterruptedException, ExecutionException {
HttpHeaders headers = headersFuture.get(); HttpHeaders headers = headersFuture.get();
return headers.getAllow(); return headers.getAllow();
} }
@Override @Override
public Set<HttpMethod> get(long timeout, TimeUnit unit) public Set<HttpMethod> get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException { throws InterruptedException, ExecutionException, TimeoutException {
@ -407,6 +393,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
}; };
} }
// exchange // exchange
@Override @Override
@ -475,6 +462,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
return execute(url, method, requestCallback, responseExtractor); return execute(url, method, requestCallback, responseExtractor);
} }
// general execution // general execution
@Override @Override
@ -496,8 +484,9 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
} }
@Override @Override
public <T> Future<T> execute(URI url, HttpMethod method, AsyncRequestCallback requestCallback, public <T> Future<T> execute(URI url, HttpMethod method,
ResponseExtractor<T> responseExtractor) throws RestClientException { AsyncRequestCallback requestCallback, ResponseExtractor<T> responseExtractor)
throws RestClientException {
return doExecute(url, method, requestCallback, responseExtractor); return doExecute(url, method, requestCallback, responseExtractor);
} }
@ -507,7 +496,6 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
* {@link org.springframework.http.client.ClientHttpRequest} * {@link org.springframework.http.client.ClientHttpRequest}
* is processed using the {@link RequestCallback}; the response with * is processed using the {@link RequestCallback}; the response with
* the {@link ResponseExtractor}. * the {@link ResponseExtractor}.
*
* @param url the fully-expanded URL to connect to * @param url the fully-expanded URL to connect to
* @param method the HTTP method to execute (GET, POST, etc.) * @param method the HTTP method to execute (GET, POST, etc.)
* @param requestCallback object that prepares the request (can be {@code null}) * @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} * @return an arbitrary object, as returned by the {@link ResponseExtractor}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> Future<T> doExecute(URI url, HttpMethod method, protected <T> Future<T> doExecute(URI url, HttpMethod method, AsyncRequestCallback requestCallback,
AsyncRequestCallback requestCallback, ResponseExtractor<T> responseExtractor) ResponseExtractor<T> responseExtractor) throws RestClientException {
throws RestClientException {
Assert.notNull(url, "'url' must not be null"); Assert.notNull(url, "'url' must not be null");
Assert.notNull(method, "'method' 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, private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse response) {
ClientHttpResponse response) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
try { try {
logger.debug("Async " + method.name() + " request for \"" + url + 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, private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException {
ClientHttpResponse response) throws IOException {
if (logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
try { try {
logger.warn("Async " + method.name() + " request for \"" + url + 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 * headers based on the given response type and configured {@linkplain
* #getMessageConverters() message converters}. * #getMessageConverters() message converters}.
*/ */
protected <T> AsyncRequestCallbackAdapter acceptHeaderRequestCallback( protected <T> AsyncRequestCallback acceptHeaderRequestCallback(Class<T> responseType) {
Class<T> responseType) { return new AsyncRequestCallbackAdapter(this.syncTemplate.acceptHeaderRequestCallback(responseType));
return new AsyncRequestCallbackAdapter(
this.syncTemplate.acceptHeaderRequestCallback(responseType));
} }
/** /**
@ -586,25 +569,21 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
* request stream. * request stream.
*/ */
protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody) { protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> requestBody) {
return new AsyncRequestCallbackAdapter( return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(requestBody));
this.syncTemplate.httpEntityCallback(requestBody));
} }
/** /**
* Returns a request callback implementation that writes the given object to the * Returns a request callback implementation that writes the given object to the
* request stream. * request stream.
*/ */
protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> request, protected <T> AsyncRequestCallback httpEntityCallback(HttpEntity<T> request, Type responseType) {
Type responseType) { return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(request, responseType));
return new AsyncRequestCallbackAdapter(
this.syncTemplate.httpEntityCallback(request, responseType));
} }
/** /**
* Returns a response extractor for {@link ResponseEntity}. * Returns a response extractor for {@link ResponseEntity}.
*/ */
protected <T> ResponseExtractor<ResponseEntity<T>> responseEntityExtractor( protected <T> ResponseExtractor<ResponseEntity<T>> responseEntityExtractor(Type responseType) {
Type responseType) {
return this.syncTemplate.responseEntityExtractor(responseType); return this.syncTemplate.responseEntityExtractor(responseType);
} }
@ -615,6 +594,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
return this.syncTemplate.headersExtractor(); return this.syncTemplate.headersExtractor();
} }
private abstract class ResponseFuture<T> implements Future<T> { private abstract class ResponseFuture<T> implements Future<T> {
private final HttpMethod method; private final HttpMethod method;
@ -623,7 +603,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
private final Future<ClientHttpResponse> responseFuture; private final Future<ClientHttpResponse> responseFuture;
protected ResponseFuture(HttpMethod method, URI url, Future<ClientHttpResponse> responseFuture) { public ResponseFuture(HttpMethod method, URI url, Future<ClientHttpResponse> responseFuture) {
this.method = method; this.method = method;
this.url = url; this.url = url;
this.responseFuture = responseFuture; this.responseFuture = responseFuture;
@ -650,8 +630,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
} }
@Override @Override
public T get(long timeout, TimeUnit unit) public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
throws InterruptedException, ExecutionException, TimeoutException {
return getInternal(this.responseFuture.get(timeout, unit)); return getInternal(this.responseFuture.get(timeout, unit));
} }
@ -685,8 +664,7 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
private final ResponseExtractor<T> responseExtractor; private final ResponseExtractor<T> responseExtractor;
private ResponseExtractorFuture(HttpMethod method, URI url, public ResponseExtractorFuture(HttpMethod method, URI url, Future<ClientHttpResponse> responseFuture,
Future<ClientHttpResponse> responseFuture,
ResponseExtractor<T> responseExtractor) { ResponseExtractor<T> responseExtractor) {
super(method, url, responseFuture); super(method, url, responseFuture);
this.responseExtractor = responseExtractor; this.responseExtractor = responseExtractor;
@ -698,10 +676,10 @@ public class AsyncRestTemplate extends AsyncHttpAccessor implements AsyncRestOpe
} }
} }
private class VoidResponseFuture extends ResponseFuture<Void> { private class VoidResponseFuture extends ResponseFuture<Void> {
private VoidResponseFuture(HttpMethod method, URI url, public VoidResponseFuture(HttpMethod method, URI url, Future<ClientHttpResponse> responseFuture) {
Future<ClientHttpResponse> responseFuture) {
super(method, url, 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();
}
});
}
}
}
} }