In Java 11, the HttpClient
API provides a modern and user-friendly way to send both synchronous and asynchronous HTTP requests. To send asynchronous requests, you’ll use the sendAsync
method, which returns a CompletableFuture
.
Here’s how to use it:
Step-by-Step Guide to Sending Asynchronous Requests:
- Initialize the
HttpClient
:
UseHttpClient
to create an instance. This is the central object for sending requests. - Create an
HttpRequest
:
Prepare your HTTP request using theHttpRequest
class, where you can specify the URI, HTTP method, headers, body, etc. - Send an Asynchronous Request with
sendAsync
:
Call thesendAsync
method of theHttpClient
, passing the request and body handler as arguments. This returns aCompletableFuture
, which allows you to perform non-blocking operations. - Process the Response:
Use theCompletableFuture
chain methods, likethenApply
andthenAccept
, to process the response once it’s available.
Example: Sending an Asynchronous GET Request
package org.kodejava.net.http;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
public class AsyncHttpClientExample {
public static void main(String[] args) {
// Create HttpClient instance
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)) // Optional timeout
.build();
// Prepare HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.GET()
.header("Accept", "application/json")
.build();
// Send asynchronous request
CompletableFuture<HttpResponse<String>> futureResponse =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Process response asynchronously
futureResponse.thenApply(HttpResponse::body) // Extract the response body
.thenAccept(System.out::println) // Print the body
.exceptionally(ex -> {
System.err.println("Request failed: " + ex.getMessage());
return null;
});
// Do other tasks while the response is being fetched...
System.out.println("Request is sent. Waiting for response...");
// Wait until the response completes to prevent the program from exiting early
futureResponse.join();
}
}
Explanation:
HttpClient.newBuilder()
:
Creates a new instance of theHttpClient
. You can optionally configure timeouts, proxies, or redirect policies.HttpRequest.newBuilder()
:
Creates an HTTP request. You specify the URI, headers, and HTTP method (e.g.,GET
,POST
, etc.).sendAsync
:
Sends the request asynchronously. It accepts two arguments:- The
HttpRequest
object. - A
BodyHandler
to determine how the HTTP response body should be handled, such asofString()
for plain text.
- The
- CompletableFuture Chain:
thenApply
: Manipulates the asynchronous result as it becomes available.thenAccept
: Consumes the result of the future once it’s ready.exceptionally
: Handles any exceptions that occur during execution.
join()
:
Blocks the main thread until the asynchronous operation is complete (used here to prevent premature termination of the program).
Example: Sending an Asynchronous POST Request with JSON Body
package org.kodejava.net.http;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
public class AsyncPostExample {
public static void main(String[] args) {
// Create HttpClient
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
// Prepare JSON body
String jsonBody = "{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": 1 }";
// Create HttpRequest
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.header("Content-Type", "application/json")
.build();
// Send asynchronous POST request
CompletableFuture<HttpResponse<String>> futureResponse =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// Handle response
futureResponse.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.exceptionally(ex -> {
System.err.println("Error: " + ex.getMessage());
return null;
});
// Keep the program running to wait for response
System.out.println("POST request sent. Waiting for response...");
futureResponse.join();
}
}
Keynotes:
- Thread-Safe
HttpClient
:
TheHttpClient
instance is thread-safe and can be reused for multiple requests. - Non-blocking Nature:
Asynchronous requests are non-blocking, so you can perform other tasks while waiting for the response. - Error Handling:
Use theexceptionally
method of theCompletableFuture
to handle any errors during the request. - Keepalive:
By default,HttpClient
connections have keepalive enabled. It’s more efficient for high-performance applications. - Timeouts:
Always configure timeouts to prevent indefinite blockage (connectTimeout
or read timeouts).
Using this approach, you can efficiently perform asynchronous HTTP communication with HttpClient
.