Migration to Apache HttpClient 5.x async APIs
HttpClient ships with a number of standard message handlers for the most common scenarios as well as a number of abstract classes that can be used as a base for custom handlers.
-
BasicAsyncEntityConsumer
,BasicAsyncEntityProducer
entity handlers that buffer entity content in memory and therefore are not much different than simple handlers. -
AbstractBinAsyncEntityConsumer
andAbstractBinAsyncEntityProducer
handlers can serve as the base classes for custom binary entity consumers or producers. -
AbstractCharAsyncEntityConsumer
andAbstractCharAsyncEntityProducer
handlers can serve as the base classes for custom character entity consumers or producers. -
FileEntityProducer
entity handler that generates data stream from a file. -
AbstractClassicEntityConsumer
andAbstractClassicEntityProducer
entity handlers that acts as a compatibility layer for classicInputStream
/OutputStream
based interfaces. Blocking input / output processing is executed through anExecutor
. -
BasicRequestProducer
andBasicResponseConsumer
messages handlers that perform no message head transformation and can use any custom entity producer or consumer to handle the message body. -
AbstractBinResponseConsumer
response handler can serve as the base class for custom binary response consumers. -
AbstractCharResponseConsumer
response handler can serve as the base class for custom character response consumers.
There are also third-party libraries that can provide specialized message handlers, for instance, for JSON message processing using Jackson JSON processor.
Migration steps
-
Depending on the preferred migration path it one might consider migrating to HttpClient 5.x classic APIs or HttpClient 5.x async APIs with simple message handlers as the first step.
-
Replace the existing request generation and response processing code with optimized message handlers shipped with HttpClient 5.x or custom-built handlers.
In this particular instance JSON message handlers are used to process JSON messages of arbitrary length without intermediate buffering of the entire message.
The general use pattern remains the same as with simple message handlers.
PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create() .setTlsStrategy(ClientTlsStrategyBuilder.create() .setSslContext(SSLContexts.createSystemDefault()) .setTlsVersions(TLS.V_1_3) .build()) .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT) .setConnPoolPolicy(PoolReusePolicy.LIFO) .setDefaultConnectionConfig(ConnectionConfig.custom() .setSocketTimeout(Timeout.ofMinutes(1)) .setConnectTimeout(Timeout.ofMinutes(1)) .setTimeToLive(TimeValue.ofMinutes(10)) .build()) .setDefaultTlsConfig(TlsConfig.custom() .setVersionPolicy(HttpVersionPolicy.NEGOTIATE) .setHandshakeTimeout(Timeout.ofMinutes(1)) .build()) .build(); CloseableHttpAsyncClient client = HttpAsyncClients.custom() .setConnectionManager(connectionManager) .setIOReactorConfig(IOReactorConfig.custom() .setSoTimeout(Timeout.ofMinutes(1)) .build()) .setDefaultRequestConfig(RequestConfig.custom() .setCookieSpec(StandardCookieSpec.STRICT) .build()) .build(); client.start(); CookieStore cookieStore = new BasicCookieStore(); CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); HttpClientContext clientContext = HttpClientContext.create(); clientContext.setCookieStore(cookieStore); clientContext.setCredentialsProvider(credentialsProvider); clientContext.setRequestConfig(RequestConfig.custom() .setCookieSpec(StandardCookieSpec.STRICT) .build()); JsonFactory jsonFactory = new JsonFactory(); ObjectMapper objectMapper = new ObjectMapper(jsonFactory); Future<?> future = client.execute( JsonRequestProducers.create( BasicRequestBuilder.post("https://httpbin.org/post").build(), Arrays.asList( new org.apache.http.message.BasicNameValuePair("name1", "value1"), new org.apache.http.message.BasicNameValuePair("name2", "value2")), objectMapper), JsonResponseConsumers.create(jsonFactory), new FutureCallback<Message<HttpResponse, JsonNode>>() { @Override public void completed(Message<HttpResponse, JsonNode> message) { System.out.println(message.getBody()); } @Override public void failed(Exception ex) { System.out.println("Error executing HTTP request: " + ex.getMessage()); } @Override public void cancelled() { System.out.println("HTTP request execution cancelled"); } }); future.get(); client.close(CloseMode.GRACEFUL);