DEV Community

Cover image for Http Client API in Java: The basics
Noe Lopez
Noe Lopez

Posted on • Edited on

11

Http Client API in Java: The basics

Overview

The new HttpClient API was introduced in Java 11. It is a replacement for the old HttpURLConnection API which was not suitable for HTTP protocol. This new API uses builder pattern and fluent API to create the required objects to communicate over the Network. It also provides the below features:

  1. Support for HTTP2 protocol.
  2. SSL encription.
  3. Synchronous and Asynchronous communication models.
  4. Support for HTTP methods.
  5. Authentication mechanism (Basic).
  6. Cookies.

The API contains three main classes:

  • HttClient is used to send multiple requests and receive the responses over the newtwork.

  • HttpRequest is an ummutable class representing an http request to be sent. It can be configured for a specific HTTP method and append the body if any.

  • HttpResponse depicts a response comming from the web server. It is returned by the HttpClient when a request is submitted. If the call is asynchronous it returns a CompletableFuture.

The steps are straightforward. First, an instance of HttpClient is created, then the HTTP request to be dispatched. Finally, the request is passed to the HttpClient send methods and a response object is returned (or CompletableFuture if the call is asynchronous).

Use Cases In Action

Without any further delay, let's take a look at some examples:

For this demo, a SpringBoot REST application will be exposing an endpoint (located in http://localhost:8080/api/v1/customers)
that allows to list/add/update/delete customers. Customer is just an ummutable POJO class with a few members. With the help of HttpClient API, we will perform CRUD operations while interacting with the service.

1. Get List of customers

The first scenario is to get a list of all customers. This is just a GET request to the customers resource URL.

HttpClient client = HttpClient
    .newBuilder()
    .connectTimeout(Duration.ofMillis(500))
    .build();
Enter fullscreen mode Exit fullscreen mode

Note that connection will time out if it is not established in half a second. Next the http request object.

HttpRequests request = HttpRequest
    .newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers"))
    .header("Content-Type", "application/json")
    .GET()
    .build();
Enter fullscreen mode Exit fullscreen mode

Now the communication can be done synchronous, that is, execution is blocked until the response is received.

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
System.out.printf("Response %s \n", response.body());
Enter fullscreen mode Exit fullscreen mode

The BodyHandlers class contains convenient methods to convert the response body data into java objects like a String.

Program Output

Status 200 
Response [
{"id":1,"name":"Joe Smith","email":"joe.smith@gmail.com","dateOfBirth":"2008-01-01"},
{"id":2,"name":"Robert Moody","email":"robert.moody@gmail.com","dateOfBirth":"1985-06-21"},
{"id":3,"name":"Jennifer Dolan","email":"jennifer.dolan@gmail.com","dateOfBirth":"1966-11-11"},
{"id":4,"name":"Christopher Farrel","email":"christopher.farrel@gmail.com","dateOfBirth":"1970-04-15"},
{"id":5,"name":"Caroline Red","email":"caroline.red@gmail.com","dateOfBirth":"1992-03-05"}
] 
Enter fullscreen mode Exit fullscreen mode

We could send the same request asynchronously invoking the sendAsynch method. This call is non-blocking and it will
return immediately a CompletableFuture.

CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());

responseFuture
    .thenApply(HttpResponse::body)
    .thenApply(String::toUpperCase)
    .thenAccept(System.out::println)
    .join();
Enter fullscreen mode Exit fullscreen mode

In the above pipeline, the body is extracted from the response, uppercased and printed.

Program Output

[
{"ID":1,"NAME":"JOE SMITH","EMAIL":"JOE.SMITH@GMAIL.COM","DATEOFBIRTH":"2008-01-01"},
{"ID":2,"NAME":"ROBERT MOODY","EMAIL":"ROBERT.MOODY@GMAIL.COM","DATEOFBIRTH":"1985-06-21"},
{"ID":3,"NAME":"JENNIFER DOLAN","EMAIL":"JENNIFER.DOLAN@GMAIL.COM","DATEOFBIRTH":"1966-11-11"},
{"ID":4,"NAME":"CHRISTOPHER FARREL","EMAIL":"CHRISTOPHER.FARREL@GMAIL.COM","DATEOFBIRTH":"1970-04-15"},
{"ID":5,"NAME":"CAROLINE RED","EMAIL":"CAROLINE.RED@GMAIL.COM","DATEOFBIRTH":"1992-03-05"}
]
Enter fullscreen mode Exit fullscreen mode

2. Create a new Customer

POST method will be used to create a new customer. The body must be populated with the customer data in JSON format. The BodyPublishers class provides handy methods to convert from java objects into a flow of data for sending as a request body.

HttpRequest request = HttpRequest
    .newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"Sonia Lamar\",\"email\":\"sonia.lamar@mail.com\",\"dateOfBirth\":\"1998-07-29\"}"))
    .build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
System.out.printf("Location %s \n", response.headers().map().get("location"));
Enter fullscreen mode Exit fullscreen mode

Program Output

Status 201 
Location [http://localhost:8080/api/v1/customers/6] 
Enter fullscreen mode Exit fullscreen mode

3. Update a new Customer

PUT method will be used to replace entirely an existing customer. That means all fields will be changed except the id. For partial updates, like updating only the email, the PATCH method is more appropiate.

HttpRequest request = HttpRequest
    .newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers/4"))
    .header("Content-Type", "application/json")
    .PUT(HttpRequest.BodyPublishers.ofString("{\"name\":\"Victor Martin\",\"email\":\"victor.martin@mail.com\",\"dateOfBirth\":\"1977-04-15\"}"))
    .build();


var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
System.out.printf("Body %s \n", response.body());
Enter fullscreen mode Exit fullscreen mode

Program Output

Status 200 
Body {"id":4,"name":"Victor Martin","email":"victor.martin@mail.com","dateOfBirth":"1977-04-15"} 
Enter fullscreen mode Exit fullscreen mode

4. Delete a new Customer

Final scenario is to delete the customer which id is 3.

var request = HttpRequest
    .newBuilder()
    .uri(URI.create("http://localhost:8080/api/v1/customers/3"))
    .header("Content-Type", "application/json")
    .DELETE()
    .build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.printf("Status %s \n", response.statusCode());
Enter fullscreen mode Exit fullscreen mode

Program Output

Status 204
Enter fullscreen mode Exit fullscreen mode

Conclusion

We learned how to use the Java HttpClient API to consume a REST web service. We performed CRUD operations using the appropiate HTTP methods and inspect the response to verify status, headers and body.

Follow up on the second part of this series and check out how to authenticate to access secured resources. Click here to learn more!

Check the code on GitHub

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay