Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to - Spring IoC and HttpClient 4.3.1 CloseableHttpClient?

I'd like to have Spring IoC configure a CloseableHttpClient object and inject it into my class so that customization of its configuration can be done via XML.

From what I can see, HttpClient seems to resist this pattern quite forcibly. They want you to do things like

CloseableHttpClient chc =
    HttpClients.custom().set<thing that should be a property>().build();

Ick.

Is there not some mechanism for making a singleton CloseableHttpClient bean that I can then use?

like image 221
nsayer Avatar asked Dec 03 '13 00:12

nsayer


People also ask

What is the difference between HttpClient and CloseableHttpClient?

The documentation seems pretty clear to me: "Base implementation of HttpClient that also implements Closeable" - HttpClient is an interface; CloseableHttpClient is an abstract class, but because it implements AutoCloseable you can use it in a try-with-resources statement.

How do I initialize CloseableHttpClient?

Create instance of CloseableHttpClient using helper class HttpClients . Create HttpGet or HttpPost instance based on the HTTP request type. Use addHeader method to add required headers such as User-Agent, Accept-Encoding etc. For POST, create list of NameValuePair and add all the form parameters.

Is CloseableHttpClient thread safe?

[Closeable]HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused for multiple request executions.

What is the use of HttpComponentsClientHttpRequestFactory?

Class HttpComponentsClientHttpRequestFactory. ClientHttpRequestFactory implementation that uses Apache HttpComponents HttpClient to create requests. Allows to use a pre-configured HttpClient instance - potentially with authentication, HTTP connection pooling, etc.


2 Answers

This seems to work for me:

<bean id="requestConfigBuilder" class="org.apache.http.client.config.RequestConfig"
    factory-method="custom">
    <property name="socketTimeout" value="${socketTimeoutInMillis}" /> 
    <property name="connectTimeout" value="${connectionTimeoutInMillis}" /> 
</bean>

<bean id="requestConfig" factory-bean="requestConfigBuilder" factory-method="build" />

<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder"
    factory-method="create">
    <property name="defaultRequestConfig" ref="requestConfig" />
</bean>

<bean id="httpClient" factory-bean="httpClientBuilder" factory-method="build" />

That gives me a CloseableHttpClient in the "httpClient" bean, with the socket and connection timeouts configured. You should be able to add more properties to either the requestConfigBuilder or the httpClientBuilder.

like image 58
Matt Avatar answered Oct 23 '22 09:10

Matt


With Java config, this is as simple as

@Bean
public CloseableHttpClient httpClient() {
    HttpClientBuilder builder = HttpClientBuilder.create();
    builder.setEverything(everything); // configure it
    CloseableHttpClient httpClient = builder.build();
}

With XML config, it's a little more complex. You can create your own FactoryBean implementation, say CloseableHttpClientFactoryBean, which delegates all the calls to a HttpClientBuilder and calls build() inside getObject().

public class CloseableHttpClientFactoryBean implements FactoryBean<CloseableHttpClient> {
    private HttpClientBuilder builder;
    public CloseableHttpClientFactoryBean() {
        builder = HttpClientBuilder.create();
    }

    ... // all the setters
    // for example
    public void setEverything(Everything everything) {
        // delegate
        builder.setEverything(everything);
    }

    public CloseableHttpClient getObject() {
        return builder.build();
    }
}

And the config

<bean name="httpClient" class="com.spring.http.clients.CloseableHttpClientFactoryBean">
    <property name="everything" ref="everything"/>
</bean>

You will need a setter method for each HttpClientBuilder method.

Note that if you don't need any custom configuration, you can use factory-method to get a default CloseableHttpClient

<bean name="httpClient" class="org.apache.http.impl.client.HttpClients" factory-method="createDefault" >
</bean>
like image 38
Sotirios Delimanolis Avatar answered Oct 23 '22 10:10

Sotirios Delimanolis