The sendAsync()
method in Java is an abstract method provided by the java.net.http.HttpClient
class. It sends an HTTP request asynchronously using the specified response body handler and returns a CompletableFuture
of the response. This allows you to perform non-blocking HTTP communication, where the request and response handling can occur concurrently with other tasks.
Table of Contents
- Introduction
sendAsync()
Method Syntax- Examples
- Basic Usage of
sendAsync()
- Handling Asynchronous Requests
- Using Push Promise Handler
- Basic Usage of
- Real-World Use Case
- Conclusion
Introduction
The HttpClient.sendAsync()
method allows you to perform asynchronous HTTP requests, enabling non-blocking operations. This method is useful in scenarios where you want to continue executing other tasks while waiting for the HTTP response, such as updating a user interface or processing other data.
sendAsync() Method Syntax
The sendAsync()
method is overloaded with two different versions:
1. sendAsync(HttpRequest, HttpResponse.BodyHandler)
public abstract <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler)
Parameters:
request
: TheHttpRequest
to be sent.responseBodyHandler
: TheHttpResponse.BodyHandler<T>
that handles the response body.
Returns:
- A
CompletableFuture<HttpResponse<T>>
that completes with the response.
2. sendAsync(HttpRequest, HttpResponse.BodyHandler, HttpResponse.PushPromiseHandler)
public abstract <T> CompletableFuture<HttpResponse<T>> sendAsync( HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, HttpResponse.PushPromiseHandler<T> pushPromiseHandler )
Parameters:
request
: TheHttpRequest
to be sent.responseBodyHandler
: TheHttpResponse.BodyHandler<T>
that handles the response body.pushPromiseHandler
: TheHttpResponse.PushPromiseHandler<T>
that handles server push promises.
Returns:
- A
CompletableFuture<HttpResponse<T>>
that completes with the response.
Examples
Basic Usage of sendAsync()
The following example demonstrates how to use the sendAsync()
method to make an asynchronous GET request to a dummy API and handle the response.
Example
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; public class HttpClientAsyncExample { public static void main(String[] args) { // Create a new HttpClient instance HttpClient httpClient = HttpClient.newHttpClient(); // Define the URI for the GET request String url = "https://jsonplaceholder.typicode.com/posts/1"; // Create an HttpRequest for the specified URI HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); // Send the request asynchronously and handle the response CompletableFuture<HttpResponse<String>> responseFuture = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()); // Process the response when it's completed responseFuture.thenAccept(response -> { System.out.println("Response Status Code: " + response.statusCode()); System.out.println("Response Body:"); System.out.println(response.body()); }); // Wait for the response to complete (optional, for demonstration) try { responseFuture.get(); // Blocks until the response is received } catch (InterruptedException | ExecutionException e) { System.out.println("Error occurred while making GET request: " + e.getMessage()); } } }
Handling Asynchronous Requests
The following example demonstrates how to handle multiple asynchronous requests and process their responses concurrently.
Example
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.concurrent.CompletableFuture; import java.util.List; public class HttpClientMultipleAsyncExample { public static void main(String[] args) { // Create a new HttpClient instance HttpClient httpClient = HttpClient.newHttpClient(); // Define URIs for the GET requests List<String> urls = List.of( "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" ); // Send requests asynchronously and collect futures List<CompletableFuture<HttpResponse<String>>> futures = urls.stream() .map(url -> sendRequestAsync(httpClient, url)) .toList(); // Process all responses when they are completed CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) .thenAccept(v -> futures.forEach(future -> { try { HttpResponse<String> response = future.get(); System.out.println("Response from " + response.uri()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Body: " + response.body()); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } })); } private static CompletableFuture<HttpResponse<String>> sendRequestAsync(HttpClient httpClient, String url) { // Create an HttpRequest for the specified URI HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); // Send the request asynchronously return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()); } }
Using Push Promise Handler
The following example demonstrates how to use a push promise handler to handle server push promises. Push promises are a feature of HTTP/2 where the server can send additional resources that the client might need in the future.
Example
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpHeaders; import java.util.concurrent.CompletableFuture; public class HttpClientPushPromiseExample { public static void main(String[] args) { // Create a new HttpClient instance with HTTP/2 support HttpClient httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .build(); // Define the URI for the GET request String url = "https://http2-push-server.example.com/resource"; // Create an HttpRequest for the specified URI HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); // Define a push promise handler HttpResponse.PushPromiseHandler<String> pushPromiseHandler = (initiatingRequest, pushPromiseRequest, acceptor) -> { System.out.println("Received push promise for: " + pushPromiseRequest.uri()); acceptor.apply(HttpResponse.BodyHandlers.ofString()) .thenAccept(response -> { System.out.println("Push Promise Response for " + response.uri() + ":"); System.out.println("Status Code: " + response.statusCode()); System.out.println("Headers: " + response.headers()); System.out.println("Body: " + response.body()); }); }; // Send the request asynchronously with the push promise handler CompletableFuture<HttpResponse<String>> responseFuture = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString(), pushPromiseHandler); // Process the main response when it's completed responseFuture.thenAccept(response -> { System.out.println("Main Response:"); System.out.println("Status Code: " + response.statusCode()); System.out.println("Body: " + response.body()); }); // Wait for all responses to complete (optional, for demonstration) try { responseFuture.join(); // Blocks until all responses are received } catch (Exception e) { System.out.println("Error occurred: " + e.getMessage()); } } }
Output:
Error occurred: java.net.ConnectException
Note: Replace https://http2-push-server.example.com/resource
with a real HTTP/2 server that supports push promises.
Explanation:
- Push Promise Handling: The
pushPromiseHandler
handles server push promises by accepting the promise and processing the response using a specified body handler. - HTTP/2 Support: The example demonstrates how to handle HTTP/2 push promises using
HttpClient
.
Real-World Use Case
Fetching Data from a REST API Asynchronously
In real-world applications, the sendAsync()
method can be used to fetch data from REST APIs asynchronously, allowing other tasks to proceed while waiting for the response.
Example
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.concurrent.CompletableFuture; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class AsyncWeatherApiExample { public static void main(String[] args) { // Create a new HttpClient instance HttpClient httpClient = HttpClient.newHttpClient(); // Define the URI for the weather API String apiKey = "your_api_key"; String city = "London"; String url = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "&appid=" + apiKey; // Create an HttpRequest for the specified URI HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .GET() .build(); // Send the request asynchronously and handle the response CompletableFuture<HttpResponse<String>> responseFuture = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()); // Process the response when it's completed responseFuture.thenAccept(response -> { try { // Parse the JSON response using Jackson ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonResponse = objectMapper.readTree(response.body()); // Extract and display weather information String weatherDescription = jsonResponse.at("/weather/0/description").asText(); double temperature = jsonResponse.at("/main/temp").asDouble() - 273.15; // Convert Kelvin to Celsius System.out.println("Weather in " + city + ": " + weatherDescription); System.out.println("Temperature: " + String.format("%.2f", temperature) + "°C"); } catch (IOException e) { System.out.println("Error parsing JSON response: " + e.getMessage()); } }); // Wait for the response to complete (optional, for demonstration) try { responseFuture.join(); // Blocks until the response is received } catch (Exception e) { System.out.println("Error occurred while fetching weather data: " + e.getMessage()); } } }
Note: Replace "your_api_key"
with your actual API key from OpenWeatherMap.
Explanation:
- Asynchronous Request: The
sendAsync()
method is used to send the request asynchronously, allowing other tasks to proceed while waiting for the response. - JSON Parsing: The example demonstrates how to parse JSON data and extract specific information using the Jackson library.
- Non-blocking Operations: The application can continue executing other tasks while waiting for the response, improving responsiveness.
Conclusion
The HttpClient.sendAsync()
method is used for performing asynchronous HTTP requests in Java. It allows you to execute non-blocking operations, enabling efficient and responsive applications. By using the HttpClient
API, you can efficiently interact with REST APIs, fetch data, and process it asynchronously in your Java applications.