Skip to content

Post SPR-8804 optimizations: better use of HC 4.3 APIs #350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 29, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.http.protocol.HttpContext;

import org.springframework.http.HttpHeaders;
Expand Down Expand Up @@ -79,7 +79,7 @@ protected Future<ClientHttpResponse> executeInternal(HttpHeaders headers,
if (this.httpRequest instanceof HttpEntityEnclosingRequest) {
HttpEntityEnclosingRequest entityEnclosingRequest =
(HttpEntityEnclosingRequest) this.httpRequest;
HttpEntity requestEntity = new ByteArrayEntity(bufferedOutput);
HttpEntity requestEntity = new NByteArrayEntity(bufferedOutput);
entityEnclosingRequest.setEntity(requestEntity);
}

Expand Down Expand Up @@ -117,14 +117,14 @@ public boolean isDone() {
public ClientHttpResponse get()
throws InterruptedException, ExecutionException {
HttpResponse response = futureResponse.get();
return new HttpComponentsClientHttpResponse(response);
return new HttpComponentsAsyncClientHttpResponse(response);
}

@Override
public ClientHttpResponse get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
HttpResponse response = futureResponse.get(timeout, unit);
return new HttpComponentsClientHttpResponse(response);
return new HttpComponentsAsyncClientHttpResponse(response);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,16 @@
import java.net.URI;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.Configurable;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.reactor.IOReactorStatus;
import org.apache.http.protocol.HttpContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
Expand All @@ -41,23 +47,23 @@ public class HttpComponentsAsyncClientHttpRequestFactory
extends HttpComponentsClientHttpRequestFactory
implements AsyncClientHttpRequestFactory, InitializingBean {

private HttpAsyncClient httpAsyncClient;
private CloseableHttpAsyncClient httpAsyncClient;


/**
* Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory}
* with a default {@link HttpAsyncClient} and {@link HttpClient}.
*/
public HttpComponentsAsyncClientHttpRequestFactory() {
this(HttpAsyncClients.createDefault());
this(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
*/
public HttpComponentsAsyncClientHttpRequestFactory(HttpAsyncClient httpAsyncClient) {
public HttpComponentsAsyncClientHttpRequestFactory(CloseableHttpAsyncClient httpAsyncClient) {
super();
Assert.notNull(httpAsyncClient, "'httpAsyncClient' must not be null");
this.httpAsyncClient = httpAsyncClient;
Expand All @@ -69,8 +75,8 @@ public HttpComponentsAsyncClientHttpRequestFactory(HttpAsyncClient httpAsyncClie
* @param httpClient the HttpClient instance to use for this request factory
* @param httpAsyncClient the HttpAsyncClient instance to use for this request factory
*/
public HttpComponentsAsyncClientHttpRequestFactory(HttpClient httpClient,
HttpAsyncClient httpAsyncClient) {
public HttpComponentsAsyncClientHttpRequestFactory(CloseableHttpClient httpClient,
CloseableHttpAsyncClient httpAsyncClient) {
super(httpClient);
Assert.notNull(httpAsyncClient, "'httpAsyncClient' must not be null");
this.httpAsyncClient = httpAsyncClient;
Expand All @@ -80,15 +86,15 @@ public HttpComponentsAsyncClientHttpRequestFactory(HttpClient httpClient,
* Set the {@code HttpClient} used for
* {@linkplain #createAsyncRequest(java.net.URI, org.springframework.http.HttpMethod) asynchronous execution}.
*/
public void setHttpAsyncClient(HttpAsyncClient httpAsyncClient) {
public void setHttpAsyncClient(CloseableHttpAsyncClient httpAsyncClient) {
this.httpAsyncClient = httpAsyncClient;
}

/**
* Return the {@code HttpClient} used for
* {@linkplain #createAsyncRequest(URI, HttpMethod) asynchronous execution}.
*/
public HttpAsyncClient getHttpAsyncClient() {
public CloseableHttpAsyncClient getHttpAsyncClient() {
return httpAsyncClient;
}

Expand All @@ -98,7 +104,7 @@ public void afterPropertiesSet() {
}

private void startAsyncClient() {
HttpAsyncClient asyncClient = getHttpAsyncClient();
CloseableHttpAsyncClient asyncClient = getHttpAsyncClient();
if (asyncClient.getStatus() != IOReactorStatus.ACTIVE) {
asyncClient.start();
}
Expand All @@ -111,8 +117,23 @@ public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod)
startAsyncClient();
HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
postProcessHttpRequest(httpRequest);
return new HttpComponentsAsyncClientHttpRequest(asyncClient, httpRequest,
createHttpContext(httpMethod, uri));
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
RequestConfig config = null;
if (httpRequest instanceof Configurable) {
config = ((Configurable) httpRequest).getConfig();
}
if (config == null) {
config = RequestConfig.DEFAULT;
}
context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
}
return new HttpComponentsAsyncClientHttpRequest(asyncClient, httpRequest, context);
}

@Override
Expand All @@ -121,7 +142,7 @@ public void destroy() throws Exception {
super.destroy();
}
finally {
getHttpAsyncClient().shutdown();
getHttpAsyncClient().close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright 2002-2012 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.http.client;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpHeaders;

import java.io.IOException;
import java.io.InputStream;

/**
* {@link ClientHttpResponse} implementation that uses
* Apache HttpComponents HttpClient to execute requests.
*
* <p>Created via the {@link HttpComponentsAsyncClientHttpRequest}.
*
* @author Oleg Kalnichevski
* @author Arjen Poutsma
* @since 3.1
* @see HttpComponentsAsyncClientHttpRequest#executeAsync()
*/
final class HttpComponentsAsyncClientHttpResponse extends AbstractClientHttpResponse {

private final HttpResponse httpResponse;

private HttpHeaders headers;


HttpComponentsAsyncClientHttpResponse(HttpResponse httpResponse) {
this.httpResponse = httpResponse;
}


@Override
public int getRawStatusCode() throws IOException {
return this.httpResponse.getStatusLine().getStatusCode();
}

@Override
public String getStatusText() throws IOException {
return this.httpResponse.getStatusLine().getReasonPhrase();
}

@Override
public HttpHeaders getHeaders() {
if (this.headers == null) {
this.headers = new HttpHeaders();
for (Header header : this.httpResponse.getAllHeaders()) {
this.headers.add(header.getName(), header.getValue());
}
}
return this.headers;
}

@Override
public InputStream getBody() throws IOException {
HttpEntity entity = this.httpResponse.getEntity();
return entity != null ? entity.getContent() : null;
}

@Override
public void close() {
// HTTP responses returned by async HTTP client
// are not bound to an active connection and
// do not have to deallocate any resources
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.util.List;
import java.util.Map;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;

Expand All @@ -46,14 +48,14 @@
*/
final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpRequest {

private final HttpClient httpClient;
private final CloseableHttpClient httpClient;

private final HttpUriRequest httpRequest;

private final HttpContext httpContext;


public HttpComponentsClientHttpRequest(HttpClient httpClient, HttpUriRequest httpRequest, HttpContext httpContext) {
public HttpComponentsClientHttpRequest(CloseableHttpClient httpClient, HttpUriRequest httpRequest, HttpContext httpContext) {
this.httpClient = httpClient;
this.httpRequest = httpRequest;
this.httpContext = httpContext;
Expand Down Expand Up @@ -81,7 +83,7 @@ protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] buffere
HttpEntity requestEntity = new ByteArrayEntity(bufferedOutput);
entityEnclosingRequest.setEntity(requestEntity);
}
HttpResponse httpResponse =
CloseableHttpResponse httpResponse =
this.httpClient.execute(this.httpRequest, this.httpContext);
return new HttpComponentsClientHttpResponse(httpResponse);
}
Expand Down
Loading