Course – LS (cat=HTTP Client-Side)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial we’ll illustrate the most common use cases of the Apache HttpAsyncClient – from basic usage, to how to set up a proxy, how to use SSL certificate and finally – how to authenticate with the async client.

2. Simple Example

First – let’s see how to use HttpAsyncClient in a simple example – send a GET request:

@Test
void whenUseHttpAsyncClient_thenCorrect() throws InterruptedException, ExecutionException, IOException {
    final SimpleHttpRequest request = SimpleRequestBuilder.get(HOST_WITH_COOKIE)
        .build();
    final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .build();
    client.start();


    final Future<SimpleHttpResponse> future = client.execute(request, null);
    final HttpResponse response = future.get();

    assertThat(response.getCode(), equalTo(200));
    client.close();
}

Note how we need to start the async client before using it; without that, we would get the following exception:

java.lang.IllegalStateException: Request cannot be executed; I/O reactor status: INACTIVE
    at o.a.h.u.Asserts.check(Asserts.java:46)
    at o.a.h.i.n.c.CloseableHttpAsyncClientBase.
      ensureRunning(CloseableHttpAsyncClientBase.java:90)

3. Multi-Threading With HttpAsyncClient

Now – let’s see how to use HttpAsyncClient to execute multiple requests simultaneously.

In the following example – we send three GET requests to three different host using HttpAsyncClient .

3.1. For HttpAsyncClient 5.x

@Test
void whenUseMultipleHttpAsyncClient_thenCorrect() throws Exception {
    final IOReactorConfig ioReactorConfig = IOReactorConfig
        .custom()
        .build();

    final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setIOReactorConfig(ioReactorConfig)
        .build();

    client.start();
    final String[] toGet = { "http://www.google.com/", "http://www.apache.org/", "http://www.bing.com/" };

    final GetThread[] threads = new GetThread[toGet.length];
    for (int i = 0; i < threads.length; i++) {
        final HttpGet request = new HttpGet(toGet[i]);
        threads[i] = new GetThread(client, request);
    }

    for (final GetThread thread : threads) {
        thread.start();
    }

    for (final GetThread thread : threads) {
        thread.join();
    }
}

Here is our GetThread implementation to handle the response:

static class GetThread extends Thread {

    private final CloseableHttpAsyncClient client;
    private final HttpContext context;
    private final HttpGet request;

    GetThread(final CloseableHttpAsyncClient client, final HttpGet request) {
        this.client = client;
        context = HttpClientContext.create();
        this.request = request;
    }

    @Override
    public void run() {
        try {
            final Future<HttpResponse> future = client.execute(request, context, null);
            final HttpResponse response = future.get();
            assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
        } catch (final Exception ex) {
            System.out.println(ex.getLocalizedMessage());
        }
    }

}

3.2. For HttpAsyncClient 4.5

@Test
void whenUseMultipleHttpAsyncClient_thenCorrect() throws Exception {
    final ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor();
    final PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(ioReactor);
    final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setConnectionManager(cm).build();
    client.start();
    final String[] toGet = { "http://www.google.com/", "http://www.apache.org/", "http://www.bing.com/" };

    final GetThread[] threads = new GetThread[toGet.length];
    for (int i = 0; i < threads.length; i++) {
        final HttpGet request = new HttpGet(toGet[i]);
        threads[i] = new GetThread(client, request);
    }

    for (final GetThread thread : threads) {
        thread.start();
    }

    for (final GetThread thread : threads) {
        thread.join();
    }

}

4. Proxy With HttpAsyncClient

Let’s see how to set up and use a proxy with the HttpAsyncClient.

In the following example – we send a HTTP GET request over proxy.

4.1. For HttpAsyncClient 5.x

@Test
void whenUseProxyWithHttpClient_thenCorrect() throws Exception {
    final HttpHost proxy = new HttpHost("127.0.0.1", GetRequestMockServer.serverPort);
    DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
    final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setRoutePlanner(routePlanner)
        .build();
    client.start();

    final SimpleHttpRequest request = new SimpleHttpRequest("GET" ,HOST_WITH_PROXY);
    final Future<SimpleHttpResponse> future = client.execute(request, null);
    final HttpResponse  response = future.get();
    assertThat(response.getCode(), equalTo(200));
    client.close();
}

4.2. For HttpAsyncClient 4.5

@Test
void whenUseProxyWithHttpClient_thenCorrect() throws Exception {
    final CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
    client.start();
    final HttpHost proxy = new HttpHost("127.0.0.1", GetRequestMockServer.serverPort);
    final RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
    final HttpGet request = new HttpGet(HOST_WITH_PROXY);
    request.setConfig(config);
    final Future<HttpResponse> future = client.execute(request, null);
    final HttpResponse response = future.get();
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

5. SSL Certificate With HttpAsyncClient

Now – let’s see how to use a SSL Certificate with HttpAsyncClient.

In the following example – we configure HttpAsyncClient to accept all certificates:

5.1. For HttpAsyncClient 5.x

@Test
void whenUseSSLWithHttpAsyncClient_thenCorrect() throws Exception {
    final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;

    final SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial(null, acceptingTrustStrategy)
        .build();

    final TlsStrategy tlsStrategy = ClientTlsStrategyBuilder.create()
        .setHostnameVerifier(NoopHostnameVerifier.INSTANCE)
        .setSslContext(sslContext)
        .build();

    final PoolingAsyncClientConnectionManager cm = PoolingAsyncClientConnectionManagerBuilder.create()
        .setTlsStrategy(tlsStrategy)
        .build();

    final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setConnectionManager(cm)
        .build();

    client.start();

    final SimpleHttpRequest request = new SimpleHttpRequest("GET",HOST_WITH_SSL);
    final Future<SimpleHttpResponse> future = client.execute(request, null);

    final HttpResponse response = future.get();
    assertThat(response.getCode(), equalTo(200));
    client.close();
}

5.2. For HttpAsyncClient 4.5

@Test
void whenUseSSLWithHttpAsyncClient_thenCorrect() throws Exception {
    final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
    final SSLContext sslContext = SSLContexts.custom()
        .loadTrustMaterial(null, acceptingTrustStrategy)
        .build();

    final CloseableHttpAsyncClient client = HttpAsyncClients.custom()
        .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
        .setSSLContext(sslContext).build();

    client.start();
    final HttpGet request = new HttpGet(HOST_WITH_SSL);
    final Future<HttpResponse> future = client.execute(request, null);
    final HttpResponse response = future.get();
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

6. Cookies With HttpAsyncClient

Next – let’s see how to use cookies with HttpAsyncClient.

In the following example – we set a cookie value before sending the request.

6.1. For HttpAsyncClient 5.x

@Test
void whenUseCookiesWithHttpAsyncClient_thenCorrect() throws Exception {
    final BasicCookieStore cookieStore = new BasicCookieStore();
    final BasicClientCookie cookie = new BasicClientCookie(COOKIE_NAME, "1234");
    cookie.setDomain(COOKIE_DOMAIN);
    cookie.setPath("/");
    cookieStore.addCookie(cookie);
    final CloseableHttpAsyncClient client = HttpAsyncClients.custom().build();
    client.start();
    final SimpleHttpRequest request = new SimpleHttpRequest("GET" ,HOST_WITH_COOKIE);

    final HttpContext localContext = new BasicHttpContext();
    localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);

    final Future<SimpleHttpResponse> future = client.execute(request, localContext, null);

    final HttpResponse response = future.get();
    assertThat(response.getCode(), equalTo(200));
    client.close();
}

6.2. For HttpAsyncClient 4.5

@Test
void whenUseCookiesWithHttpAsyncClient_thenCorrect() throws Exception {
    final BasicCookieStore cookieStore = new BasicCookieStore();
    final BasicClientCookie cookie = new BasicClientCookie(COOKIE_NAME, "1234");
    cookie.setDomain(COOKIE_DOMAIN);
    cookie.setPath("/");
    cookieStore.addCookie(cookie);
    final CloseableHttpAsyncClient client = HttpAsyncClients.custom().build();
    client.start();
    final HttpGet request = new HttpGet(HOST_WITH_COOKIE);

    final HttpContext localContext = new BasicHttpContext();
    localContext.setAttribute(HttpClientContext.COOKIE_STORE, cookieStore);

    final Future<HttpResponse> future = client.execute(request, localContext, null);
    final HttpResponse response = future.get();
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

7. Authentication With HttpAsyncClient

Next – let’s see how to use authentication with HttpAsyncClient.

In the following example – we use the CredentialsProvider to access a host through basic authentication.

7.1. For HttpAsyncClient 5.x

@Test
void whenUseAuthenticationWithHttpAsyncClient_thenCorrect() throws Exception {
    final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
    final UsernamePasswordCredentials credentials =
        new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS.toCharArray());
    credsProvider.setCredentials(new AuthScope(URL_SECURED_BY_BASIC_AUTHENTICATION, 80) ,credentials);
    final CloseableHttpAsyncClient client = HttpAsyncClients
        .custom()
        .setDefaultCredentialsProvider(credsProvider).build();

    final SimpleHttpRequest request = new SimpleHttpRequest("GET" ,URL_SECURED_BY_BASIC_AUTHENTICATION);

    client.start();

    final Future<SimpleHttpResponse> future = client.execute(request, null);

    final HttpResponse response = future.get();
    assertThat(response.getCode(), equalTo(200));
    client.close();
}

7.2. For HttpAsyncClient 4.5

@Test
public void whenUseAuthenticationWithHttpAsyncClient_thenCorrect() throws Exception {
    CredentialsProvider provider = new BasicCredentialsProvider();
    UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "pass");
    provider.setCredentials(AuthScope.ANY, creds);
    
    CloseableHttpAsyncClient client = 
      HttpAsyncClients.custom().setDefaultCredentialsProvider(provider).build();
    client.start();
    
    HttpGet request = new HttpGet("http://localhost:8080");
    Future<HttpResponse> future = client.execute(request, null);
    HttpResponse response = future.get();
    
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();
}

8. Conclusion

In this article, we illustrated the various use cases of the asynchronous Apache Http client.

As always, the complete source code is available over on GitHub. For HttpClient 4.x code snippets, please refer to our HttpClient 4 module.

Course – LS (cat=HTTP Client-Side)
announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

res – HTTP Client (eBook) (cat=Http Client-Side)