Java HttpClient

Jakob Jenkov
Last update: 2024-07-13

The Java HttpClient was added to Java in Java 11 - and provides an easy-to-use API for making HTTP 1.1 and HTTP 2.0 requests to web servers. The Java HttpClient also supports web socket communication (though I still have not found a good example showcasing how to use websockets with the Java HttpClient).

Importing the Java HttpClient

Before you can use the Java HttpClient class you must of course import it into the class using it. The HttpClient class is located in the package

java.net.http

so it's fully qualified name is

java.net.http.HttpClient

Thus, importing it will look like this:

import java.net.http.HttpClient

Creating a Java HttpClient

To use the Java HttpClient you must first create an instance of the HttpClient class. Here is how you create an instance of the Java HttpClient class:

HttpClient client = HttpClient.newBuilder().build();

You can configure the HttpClient before creating it - via the builder returned from HttpClient.newBuilder(). Here is an example of configuring the HttpClient before creating it:

HttpClient client =
    HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .build();

Creating an HttpRequest

To send an HTTP request using the Java HttpClient you must first create an instance of HttpRequest which represents that HTTP request.

The HttpRequest class is also located in java.net.http and you must import it in order to use it.

Here is an example of creating an HttpRequest instance:

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://jenkov.com/"))
        .timeout(Duration.ofSeconds(20))
        .build()
        ;

As you can see, it is also possible to configure the HttpRequest via the builder returned by HttpRequest.newBuilder() before creating the final HttpRequest instance.

Sending the HttpRequest

To execute the HTTP request you must call the HttpClient send() method and pass the HttpRequest object to it as parameter. Additionally, you must provide a BodyHandler implementation which can handle the response coming back from the HTTP server. Java comes with a set of built-in implementations of the BodyHandler interface, so you don't have to implement this interface for the most trivial cases.

Here is an example of executing an HTTP request using the Java HttpClient class :

try {

    HttpResponse<byte[]> response = client.<byte[]>send(request, HttpResponse.BodyHandlers.ofByteArray());
    byte[] body = response.body();

} catch (IOException e) {
    throw new RuntimeException(e);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

As you can see, the HttpClient send() method returns an HttpResponse object. This HttpResponse object has a generic type. In the case above, its generic type is byte[]. This means, that the body of the HTTP response will be returned as a byte array. As you can see, when you call the HttpResponse body() method, it returns a byte array.

The generic type of the returned HttpResponse object is specified just before the send() method call. The generic type of the BodyHandler implementation passed as parameter to the send() method (2nd parameter) much match the generic type specified before the send() method (and thus have to match the generic type of the HttpResponse object). In the example above, the generic type of the BodyHandler returned by HttpResponse.BodyHandlers.ofByteArray() is byte[] .

Sending the HttpRequest Asynchronously

The Java HttpClient class has a method called sendAsync() that enables you to send an HTTP request asynchronously. Here is an example of sending an HTTP request asynchronously using the HttpClient sendAsync() method:

CompletableFuture<HttpResponse<byte[]>> responseFuture =
        client.<byte[]>sendAsync(request, HttpResponse.BodyHandlers.ofByteArray());

byte[] body = responseFuture.join().body();

The HttpClient sendAsync() method returns a CompletableFuture instance with a generic type of HttpResponse, and this HttpResponse has a generic type of byte[]. Again, the byte[] generic type has to match the generic type specified before the sendAsync() call, as well as the generic type of the BodyHandler passed as 2nd parameter to the sendAsync() method. As you can see, this is the case in the example above.

The join() method of the CompletableFuture blocks until a response has been obtained inside the CompletableFuture. Once that has been obtained it will be returned by the join() method. The returned object will be of the generic type of the CompletableFuture. In this example that generic type is HttpResponse<byte[]> .

From the HttpResponse<byte[]> object returned from the join() method of the CompletableFuture, you can obtain the body of the HTTP response. This is done by calling the HttpResponse body() method. The type returned will be of the generic type of the HttpResponse object. In the example above that generic type is byte[].

Setting the HTTP Protocol Version

You can set the version of the HTTP protocol you want the Java HttpClient to use. So far, the Java HttpCliennt supports HTTP 1.1 and HTTP 2.0. You have already seen it in examples earlier, but here is how setting the HTTP version on the HttpClient looks:

HttpClient client =
    HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .build();

This example sets the HTTP protocol version to use to HTTP 1.1 .

You can also set the HTTP protocol version to HTTP 2.0. Here is how that looks:

HttpClient client =
    HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .build();

Getting the HTTP Protocol Version

If you have a Java HttpClient and you want to know what version of the HTTP protocol it is configured to support, you can call its version() method. Here is how calling the version() method on an HttpClient looks:

HttpClient client =  HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

HttpClient.Version version = client.version();
System.out.println(version);

Unzipping the Response

If the response sent back from the HTTP server is ZIP compressed, you can unzip it using the Java GZipInputStream . Basically, what you do is that you take the bytes obtained via the HttpResponse object and pass them to a GZipInputStream, from which you can then get the unzipped bytes. Here is an example of how unzipping (decompressing) an HTTP response with the Java HttpClient looks:

try {
    HttpResponse<byte[]> response = client.<byte[]>send(request, HttpResponse.BodyHandlers.ofByteArray());
    byte[] zippedResponseBody = response.body();

    GZIPInputStream inputStream = new GZIPInputStream(new ByteArrayInputStream(zippedResponseBody));
    byte[] unzippedResponseBytes = inputStream.readAllBytes();

    System.out.println(zippedResponseBody.length);
    System.out.println(unzippedResponseBytes.length);

    System.out.println(new String(unzippedResponseBytes, StandardCharsets.UTF_8));

} catch (IOException e) {
    throw new RuntimeException(e);
} catch (InterruptedException e) {
    throw new RuntimeException(e);
}

Jakob Jenkov

Featured Videos

Java ForkJoinPool

P2P Networks Introduction




















Advertisements

High-Performance
Java Persistence
Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next