From 7b5f96c804fcb34fe0157d6709ca6e25be91e5c3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 14 Jun 2017 17:10:44 +0200 Subject: [PATCH] HttpComponentsAsyncClientHttpRequestFactory supports plain HttpAsyncClient as well Issue: SPR-15664 --- ...mponentsAsyncClientHttpRequestFactory.java | 102 ++++++++++++++---- ...ttpComponentsClientHttpRequestFactory.java | 23 ++-- 2 files changed, 90 insertions(+), 35 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java index c7d9564bb6f..ea2baaa4fd1 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java @@ -16,6 +16,7 @@ package org.springframework.http.client; +import java.io.Closeable; import java.io.IOException; import java.net.URI; @@ -49,7 +50,7 @@ import org.springframework.util.Assert; public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory implements AsyncClientHttpRequestFactory, InitializingBean { - private CloseableHttpAsyncClient httpAsyncClient; + private HttpAsyncClient asyncClient; /** @@ -57,49 +58,98 @@ public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsC * with a default {@link HttpAsyncClient} and {@link HttpClient}. */ public HttpComponentsAsyncClientHttpRequestFactory() { - this(HttpAsyncClients.createSystem()); + super(); + this.asyncClient = HttpAsyncClients.createSystem(); } /** * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} * with the given {@link HttpAsyncClient} instance and a default {@link HttpClient}. - * @param httpAsyncClient the HttpAsyncClient instance to use for this request factory + * @param asyncClient the HttpAsyncClient instance to use for this request factory + * @since 4.3.10 + */ + public HttpComponentsAsyncClientHttpRequestFactory(HttpAsyncClient asyncClient) { + super(); + setAsyncClient(asyncClient); + } + + /** + * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} + * with the given {@link CloseableHttpAsyncClient} instance and a default {@link HttpClient}. + * @param asyncClient the CloseableHttpAsyncClient instance to use for this request factory */ - public HttpComponentsAsyncClientHttpRequestFactory(CloseableHttpAsyncClient httpAsyncClient) { + public HttpComponentsAsyncClientHttpRequestFactory(CloseableHttpAsyncClient asyncClient) { super(); - Assert.notNull(httpAsyncClient, "HttpAsyncClient must not be null"); - this.httpAsyncClient = httpAsyncClient; + setAsyncClient(asyncClient); } /** * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} * with the given {@link HttpClient} and {@link HttpAsyncClient} instances. * @param httpClient the HttpClient instance to use for this request factory - * @param httpAsyncClient the HttpAsyncClient instance to use for this request factory + * @param asyncClient the HttpAsyncClient instance to use for this request factory + * @since 4.3.10 + */ + public HttpComponentsAsyncClientHttpRequestFactory(HttpClient httpClient, HttpAsyncClient asyncClient) { + super(httpClient); + setAsyncClient(asyncClient); + } + + /** + * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} + * with the given {@link CloseableHttpClient} and {@link CloseableHttpAsyncClient} instances. + * @param httpClient the CloseableHttpClient instance to use for this request factory + * @param asyncClient the CloseableHttpAsyncClient instance to use for this request factory */ public HttpComponentsAsyncClientHttpRequestFactory( - CloseableHttpClient httpClient, CloseableHttpAsyncClient httpAsyncClient) { + CloseableHttpClient httpClient, CloseableHttpAsyncClient asyncClient) { super(httpClient); - Assert.notNull(httpAsyncClient, "HttpAsyncClient must not be null"); - this.httpAsyncClient = httpAsyncClient; + setAsyncClient(asyncClient); } /** - * Set the {@code HttpClient} used for + * Set the {@code HttpAsyncClient} used for + * {@linkplain #createAsyncRequest(URI, HttpMethod) synchronous execution}. + * @since 4.3.10 + * @see #setHttpClient(HttpClient) + */ + public void setAsyncClient(HttpAsyncClient asyncClient) { + Assert.notNull(asyncClient, "HttpAsyncClient must not be null"); + this.asyncClient = asyncClient; + } + + /** + * Return the {@code HttpAsyncClient} used for + * {@linkplain #createAsyncRequest(URI, HttpMethod) synchronous execution}. + * @since 4.3.10 + * @see #getHttpClient() + */ + public HttpAsyncClient getAsyncClient() { + return this.asyncClient; + } + + /** + * Set the {@code CloseableHttpAsyncClient} used for * {@linkplain #createAsyncRequest(URI, HttpMethod) asynchronous execution}. + * @deprecated as of 4.3.10, in favor of {@link #setAsyncClient(HttpAsyncClient)} */ - public void setHttpAsyncClient(CloseableHttpAsyncClient httpAsyncClient) { - this.httpAsyncClient = httpAsyncClient; + @Deprecated + public void setHttpAsyncClient(CloseableHttpAsyncClient asyncClient) { + this.asyncClient = asyncClient; } /** - * Return the {@code HttpClient} used for + * Return the {@code CloseableHttpAsyncClient} used for * {@linkplain #createAsyncRequest(URI, HttpMethod) asynchronous execution}. + * @deprecated as of 4.3.10, in favor of {@link #getAsyncClient()} */ + @Deprecated public CloseableHttpAsyncClient getHttpAsyncClient() { - return this.httpAsyncClient; + Assert.state(this.asyncClient == null || this.asyncClient instanceof CloseableHttpAsyncClient, + "No CloseableHttpAsyncClient - use getAsyncClient() instead"); + return (CloseableHttpAsyncClient) this.asyncClient; } @@ -109,22 +159,26 @@ public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsC } private void startAsyncClient() { - CloseableHttpAsyncClient asyncClient = getHttpAsyncClient(); - if (!asyncClient.isRunning()) { - asyncClient.start(); + HttpAsyncClient asyncClient = getAsyncClient(); + if (asyncClient instanceof CloseableHttpAsyncClient) { + CloseableHttpAsyncClient closeableAsyncClient = (CloseableHttpAsyncClient) asyncClient; + if (!closeableAsyncClient.isRunning()) { + closeableAsyncClient.start(); + } } } @Override public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException { - HttpAsyncClient asyncClient = getHttpAsyncClient(); startAsyncClient(); + HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri); postProcessHttpRequest(httpRequest); HttpContext context = createHttpContext(httpMethod, uri); if (context == null) { context = HttpClientContext.create(); } + // Request configuration not set in the context if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) { // Use request configuration given by the user, when available @@ -133,13 +187,14 @@ public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsC config = ((Configurable) httpRequest).getConfig(); } if (config == null) { - config = createRequestConfig(asyncClient); + config = createRequestConfig(getAsyncClient()); } if (config != null) { context.setAttribute(HttpClientContext.REQUEST_CONFIG, config); } } - return new HttpComponentsAsyncClientHttpRequest(asyncClient, httpRequest, context); + + return new HttpComponentsAsyncClientHttpRequest(getAsyncClient(), httpRequest, context); } @Override @@ -148,7 +203,10 @@ public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsC super.destroy(); } finally { - getHttpAsyncClient().close(); + HttpAsyncClient asyncClient = getAsyncClient(); + if (asyncClient instanceof Closeable) { + ((Closeable) asyncClient).close(); + } } } diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java index e7259ae32a5..9eea0f02a5d 100644 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java @@ -71,7 +71,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest * with a default {@link HttpClient}. */ public HttpComponentsClientHttpRequestFactory() { - this(HttpClients.createSystem()); + this.httpClient = HttpClients.createSystem(); } /** @@ -80,8 +80,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest * @param httpClient the HttpClient instance to use for this request factory */ public HttpComponentsClientHttpRequestFactory(HttpClient httpClient) { - Assert.notNull(httpClient, "HttpClient must not be null"); - this.httpClient = httpClient; + setHttpClient(httpClient); } @@ -90,6 +89,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest * {@linkplain #createRequest(URI, HttpMethod) synchronous execution}. */ public void setHttpClient(HttpClient httpClient) { + Assert.notNull(httpClient, "HttpClient must not be null"); this.httpClient = httpClient; } @@ -97,7 +97,6 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest * Return the {@code HttpClient} used for * {@linkplain #createRequest(URI, HttpMethod) synchronous execution}. */ - @Nullable public HttpClient getHttpClient() { return this.httpClient; } @@ -153,9 +152,6 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - HttpClient client = getHttpClient(); - Assert.state(client != null, "Synchronous execution requires an HttpClient to be set"); - HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri); postProcessHttpRequest(httpRequest); HttpContext context = createHttpContext(httpMethod, uri); @@ -171,7 +167,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest config = ((Configurable) httpRequest).getConfig(); } if (config == null) { - config = createRequestConfig(client); + config = createRequestConfig(getHttpClient()); } if (config != null) { context.setAttribute(HttpClientContext.REQUEST_CONFIG, config); @@ -179,10 +175,10 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest } if (this.bufferRequestBody) { - return new HttpComponentsClientHttpRequest(client, httpRequest, context); + return new HttpComponentsClientHttpRequest(getHttpClient(), httpRequest, context); } else { - return new HttpComponentsStreamingClientHttpRequest(client, httpRequest, context); + return new HttpComponentsStreamingClientHttpRequest(getHttpClient(), httpRequest, context); } } @@ -301,8 +297,9 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest */ @Override public void destroy() throws Exception { - if (this.httpClient instanceof Closeable) { - ((Closeable) this.httpClient).close(); + HttpClient httpClient = getHttpClient(); + if (httpClient instanceof Closeable) { + ((Closeable) httpClient).close(); } } @@ -312,7 +309,7 @@ public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequest * extends {@link org.apache.http.client.methods.HttpEntityEnclosingRequestBase} * rather than {@link org.apache.http.client.methods.HttpRequestBase} and * hence allows HTTP delete with a request body. For use with the RestTemplate - * exchange methods which allow the combination of HTTP DELETE with entity. + * exchange methods which allow the combination of HTTP DELETE with an entity. * @since 4.1.2 */ private static class HttpDelete extends HttpEntityEnclosingRequestBase {