Apache HttpClient

Apache HttpClient is an open source Java HTTP client.

Connection Pooling

Use PoolingHttpClientConnectionManager to utilize a pool of connections. A connection pool defaults to 25 total maximum connections and 5 maximum connections per route. Change these values by calling setMaxTotal and setDefaultMaxPerRoute, respectively. Then call HttpClients.custom() followed by setConnectionManager to use the pooled connection manager and finally call build to get the connection.

Keep-Alive

Keep-alive behavior is configured with HttpClientBuilder.setConnectionReuseStrategy and HttpClientBuilder.setKeepAliveStrategy.

The default implementation of the former is DefaultConnectionReuseStrategy which uses keep-alive unless common response headers like Connection: close are processed.

The default implementation of the latter is DefaultConnectionKeepAliveStrategy which uses keep-alive for an unlimited time unless the Keep-Alive response header is specified.

User Token Handler

The default user token handler stores state about a user principal from the execution context or mutual TLS authentication session into a connection, if available. This means that such connections cannot be re-used by different user principals and thus may severely limit connection pool re-use. Alternatively, you may call setUserTokenHandler with NoopUserTokenHandler.INSTANCE to avoid this behavior if the security implications are acceptable.

Example

  1. Add dependencies to pom.xml: https://search.maven.org/artifact/org.apache.httpcomponents.client5/httpclient5
      <dependencies>
        <dependency>
          <groupId>org.apache.httpcomponents.client5</groupId>
          <artifactId>httpclient5</artifactId>
          <version>5.1.3</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-api</artifactId>
          <version>1.7.36</version>
        </dependency>
        <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>slf4j-simple</artifactId>
          <version>1.7.36</version>
        </dependency>
      </dependencies>
  2. Add client code:
    package com.example.java;
    
    import org.apache.hc.client5.http.classic.methods.HttpGet;
    import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
    import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
    import org.apache.hc.client5.http.impl.classic.HttpClients;
    import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
    import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
    import org.apache.hc.core5.http.io.entity.EntityUtils;
    
    public class App {
      public static final int MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_TOTAL = Integer
          .getInteger("MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_TOTAL", 100);
    
      public static final int MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_PER_ROUTE = Integer
          .getInteger("MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_PER_ROUTE", MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_TOTAL);
    
      public static final PoolingHttpClientConnectionManager HTTP_CLIENT_CONNECTION_MANAGER = PoolingHttpClientConnectionManagerBuilder
          .create().setMaxConnTotal(MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_TOTAL)
          .setMaxConnPerRoute(MAX_HTTP_CLIENT_OUTBOUND_CONNECTIONS_PER_ROUTE).build();
    
      public static void main(String[] args) throws Throwable {
        try (CloseableHttpClient httpClient = HttpClients.custom()
            .setConnectionManager(HTTP_CLIENT_CONNECTION_MANAGER)
            .setConnectionManagerShared(true)
            .build()) {
          try (CloseableHttpResponse response = httpClient.execute(new HttpGet("https://example.org/"))) {
            System.out.println(response.getCode() + " " + EntityUtils.toString(response.getEntity()));
          }
        }
      }
    }

Debugging HttpClient

Try:

-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog 
-Dorg.apache.commons.logging.simplelog.showdatetime=true 
-Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG 
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=ERROR 
-Dorg.apache.commons.logging.simplelog.log.org.apache.http.headers=ERROR