How do I Use HttpClient to Call REST APIs?

Java 11 introduced a new HttpClient API (java.net.HttpClient) that simplifies making HTTP requests and handling responses. It provides a clean and concise way to perform synchronous and asynchronous HTTP operations, and it fully supports RESTful APIs.

Here’s a step-by-step guide with examples for how to use the Java 11 HttpClient to call REST APIs.


1. Create an HttpClient Instance

The HttpClient is the main entry point for sending HTTP requests and receiving responses. You can create an HttpClient using its builder.

HttpClient client = HttpClient.newHttpClient();

2. Build an HttpRequest

The HttpRequest represents the HTTP request that you want to send. You can build it using a static builder where you set the HTTP method, headers, URI, etc.

Example: Build a GET Request

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
        .GET() // Use GET method
        .build();

Example: Build a POST Request

For a POST request, you also need to include a body in the request.

HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
        .header("Content-Type", "application/json")
        .POST(HttpRequest.BodyPublishers.ofString("{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}"))
        .build();

3. Send the HttpRequest

The HttpClient provides methods to send HTTP requests. You can choose to execute the request synchronously or asynchronously.

Synchronous Call

Use HttpClient.send() to execute the request synchronously and retrieve an HttpResponse.

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());

Asynchronous Call

Use HttpClient.sendAsync() to execute the request asynchronously. It returns a CompletableFuture which allows non-blocking operations.

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
      .thenApply(HttpResponse::body) // Extract body
      .thenAccept(System.out::println); // Print response body

The above code sends the request in the background and processes the response once received.


4. Handle Response

The HttpResponse provides access to the response details like status code, headers, and body. You can use HttpResponse.BodyHandlers to specify how the body should be processed.

Available BodyHandlers:

  • HttpResponse.BodyHandlers.ofString(): Read the response as a String.
  • HttpResponse.BodyHandlers.ofFile(): Save the response to a file.
  • HttpResponse.BodyHandlers.ofInputStream(): Access the response as an InputStream.

For example:

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Headers: " + response.headers());
System.out.println("Body: " + response.body());

5. Complete Example for a GET Request

Here’s a complete program that sends a GET request to a REST API and prints the response:

package org.kodejava.net.http;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class HttpClientGetExample {
    public static void main(String[] args) {
        try {
            // Step 1: Create HttpClient
            HttpClient client = HttpClient.newHttpClient();

            // Step 2: Create HttpRequest
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
                    .GET()
                    .build();

            // Step 3: Send the request and receive HttpResponse
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            // Step 4: Process the response
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6. Complete Example for a POST Request

Here’s how you can do a POST request to send JSON data:

package org.kodejava.net.http;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class HttpClientPostExample {
    public static void main(String[] args) {
        try {
            // Step 1: Create HttpClient
            HttpClient client = HttpClient.newHttpClient();

            // Step 2: Build HttpRequest with POST body
            HttpRequest request = HttpRequest.newBuilder()
                    .uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
                    .header("Content-Type", "application/json")
                    .POST(HttpRequest.BodyPublishers.ofString("{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}"))
                    .build();

            // Step 3: Send the POST request and receive response
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            // Step 4: Process the response
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Key Points to Remember:

  1. Use java.net.URI for specifying the API endpoint.
  2. Always handle exceptions (e.g., IOException and InterruptedException).
  3. You may need to set headers (e.g., Content-Type or Authorization) depending on the API requirements.
  4. Handle different response codes appropriately.

This approach is suitable for working with REST APIs and provides both blocking and non-blocking operations for flexibility.

How do I Send Requests Using Different HTTP Methods with HttpClient?

Java 11 introduced the HttpClient API to simplify and modernize HTTP communications. This API supports sending requests using different HTTP methods (GET, POST, PUT, DELETE, etc.). Below is an explanation and example of how to perform these operations.

1. Setup

You will use the HttpClient and related classes from java.net.http package:

  • HttpClient – To execute HTTP requests.
  • HttpRequest – To construct and describe HTTP requests.
  • HttpResponse – To handle HTTP responses.

2. Example Code

Here’s how you can send HTTP requests with different methods using HttpClient in Java 11.

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.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;

public class HttpClientMethodExample {
   public static void main(String[] args) {
      try {
         // Create an HttpClient instance
         HttpClient httpClient = HttpClient.newHttpClient();

         // Example: GET Request
         HttpRequest getRequest = HttpRequest.newBuilder()
                 .uri(new URI("https://jsonplaceholder.typicode.com/posts/1"))
                 .GET() // Default is GET, this is optional
                 .build();
         HttpResponse<String> getResponse = httpClient.send(getRequest, BodyHandlers.ofString());
         System.out.println("GET Response: " + getResponse.body());

         // Example: POST Request
         HttpRequest postRequest = HttpRequest.newBuilder()
                 .uri(new URI("https://jsonplaceholder.typicode.com/posts"))
                 .POST(BodyPublishers.ofString("{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}"))
                 .header("Content-Type", "application/json")
                 .build();
         HttpResponse<String> postResponse = httpClient.send(postRequest, BodyHandlers.ofString());
         System.out.println("POST Response: " + postResponse.body());

         // Example: PUT Request
         HttpRequest putRequest = HttpRequest.newBuilder()
                 .uri(new URI("https://jsonplaceholder.typicode.com/posts/1"))
                 .PUT(BodyPublishers.ofString("{\"id\":1,\"title\":\"updated\",\"body\":\"new content\",\"userId\":1}"))
                 .header("Content-Type", "application/json")
                 .build();
         HttpResponse<String> putResponse = httpClient.send(putRequest, BodyHandlers.ofString());
         System.out.println("PUT Response: " + putResponse.body());

         // Example: DELETE Request
         HttpRequest deleteRequest = HttpRequest.newBuilder()
                 .uri(new URI("https://jsonplaceholder.typicode.com/posts/1"))
                 .DELETE()
                 .build();
         HttpResponse<String> deleteResponse = httpClient.send(deleteRequest, BodyHandlers.ofString());
         System.out.println("DELETE Response Code: " + deleteResponse.statusCode());

      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

3. Explanation

  1. HttpClient Creation: The HttpClient instance is reusable for making multiple requests.
  2. GET Request:
    • Use .GET() method to send a GET request.
    • Response is parsed as a String using BodyHandlers.ofString().
  3. POST Request:
    • Use .POST(BodyPublishers.ofString(content)) to send a POST request with a payload.
    • Set the Content-Type header for JSON or other content types.
  4. PUT Request:
    • Use .PUT(BodyPublishers.ofString(content)) for PUT requests with a payload.
    • Similar to POST, set the proper headers.
  5. DELETE Request:
    • Use .DELETE() to send DELETE requests.
    • Rarely includes a body; that’s why no publisher is used.
  6. Error Handling:
    • Be sure to include error handling for exceptions such as IOException and InterruptedException.

4. Output Example

If you run the code using the example endpoints, the output might look something like this:

GET Response: {
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
POST Response: {
  "title": "foo",
  "body": "bar",
  "userId": 1,
  "id": 101
}
PUT Response: {
  "id": 1,
  "title": "updated",
  "body": "new content",
  "userId": 1
}
DELETE Response Code: 200

5. Notes

  • You’ll need an API endpoint that supports CRUD operations for realistic testing.
  • Avoid hardcoding URIs in production; keep them configurable.
  • Handle response status codes appropriately for error cases (like 404, 500).

This approach provides a clean and modern way to work with HTTP in Java!

How do I set a timeout on HTTP requests in Java 11?

To set a timeout on HTTP requests in Java 11, you can use the HttpClient provided by the java.net.http module. The HttpClient API allows you to configure timeouts for requests in a convenient and standardized way.

Here’s how you can do it:

  1. Set a Connection Timeout: This controls the timeout when establishing a connection to the target server.
  2. Set a Read Timeout: This sets the timeout for reading data once the connection is established.

Here is an example demonstrating how to configure both:

Code Example

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;

public class HttpTimeoutExample {
   public static void main(String[] args) {
      // Create an HttpClient with a timeout configuration
      HttpClient client = HttpClient.newBuilder()
              .connectTimeout(Duration.ofSeconds(5)) // Set connection timeout
              .build();

      // Create an HttpRequest
      HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://example.com"))
              .timeout(Duration.ofSeconds(10)) // Set request timeout
              .GET()
              .build();

      try {
         // Send the request and receive the response
         HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
         System.out.println("Response status code: " + response.statusCode());
         System.out.println("Response body: " + response.body());
      } catch (Exception e) {
         System.err.println("Request failed: " + e.getMessage());
      }
   }
}

Explanation

  1. Connection Timeout:
    • Configured on the HttpClient with connectTimeout(Duration).
    • This defines how long the client will wait while attempting to establish a connection with the server.
  2. Request Timeout:
    • Configured on the HttpRequest with timeout(Duration).
    • This defines how long the request will wait for a complete response after connection establishment.
  3. Error Handling:
    • For failed requests (e.g., timeouts), you should catch and handle exceptions like java.net.http.HttpTimeoutException or log a generic failure as shown above.

Notes

  • If either of the timeouts is exceeded, you will get an exception that can be handled to retry, alert, or further process as needed.
  • Both settings are optional. If not configured, the client will use default timeouts per its implementation.

How do I set custom headers in Java 11 HttpRequest?

In Java 11, the java.net.http package introduced the new HttpClient API, which simplifies working with HTTP requests and responses. To set custom headers for an HttpRequest, you can use the headers method or the setHeader method while building your request using the HttpRequest.Builder.

Here’s a step-by-step guide for setting custom headers:

Example Code

package org.kodejava.net.http;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class CustomHeadersExample {

   public static void main(String[] args) throws Exception {
      // Create an HttpClient
      HttpClient client = HttpClient.newHttpClient();

      // Create a request with custom headers
      HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://example.com"))
              .header("Custom-Header", "HeaderValue") // Set custom single header
              .headers("Another-Header", "AnotherValue", "Yet-Another-Header", "YetAnotherValue") // Multiple headers
              .GET() // Specify HTTP method
              .build();

      // Send the request and print the response
      HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
      System.out.println("Response code: " + response.statusCode());
      System.out.println("Response body: " + response.body());
   }
}

Key Points in the Code

  1. Create HttpClient: The HttpClient is created using HttpClient.newHttpClient().
  2. Building the Request:
    • Use .header(String name, String value) to set a single custom header.
    • Use .headers(String... headers) to set multiple custom headers. Pass alternating key-value pairs as arguments.
    • Specify the URI and the HTTP method (GET, POST, etc.).
  3. Send the Request: The HttpClient sends the request using the .send() method and handles the response.

Notes:

  • Headers get overridden: If you call .header or .headers multiple times on the same HttpRequest.Builder, later calls for the same key will replace previous header values.
  • Thread Safety: The HttpClient instance is immutable and thread-safe, so you can reuse it for multiple requests.
  • Custom Headers: Use custom headers for tasks like authentication (e.g., Authorization headers), caching, or API versioning.

How do I handle HTTP response status codes with Java 11 HttpClient?

Handling HTTP response status codes with Java 11’s HttpClient API involves making a request, receiving a response, and then checking the status code returned in the response.

Here’s how you can do this:

Steps to Handle HTTP Response Status Codes

  1. Create the HttpClient: Build an instance of HttpClient.
  2. Build the Request: Define the HTTP request (e.g., GET, POST, etc.) with the target URI.
  3. Send the Request: Use HttpClient to send the request and receive an HttpResponse.
  4. Handle the Response: Extract and handle the HTTP response status code from the HttpResponse.

Here’s sample code to demonstrate these steps:

package org.kodejava.net.http;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class HttpClientExample {
    public static void main(String[] args) {
        // Step 1: Create an HttpClient
        HttpClient client = HttpClient.newHttpClient();

        // Step 2: Build the Request
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://jsonplaceholder.typicode.com/posts/1")) // Replace with your endpoint
                .GET()
                .build();

        try {
            // Step 3: Send the Request and Receive the Response
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            // Step 4: Handle the Response Status Code
            int statusCode = response.statusCode();
            if (statusCode >= 200 && statusCode < 300) {
                // Handle successful responses (e.g., HTTP 200 OK)
                System.out.println("Response: " + response.body());
            } else if (statusCode >= 400 && statusCode < 500) {
                // Handle client errors (e.g., HTTP 404 Not Found)
                System.err.println("Client error: " + statusCode);
            } else if (statusCode >= 500) {
                // Handle server errors (e.g., HTTP 500 Internal Server Error)
                System.err.println("Server error: " + statusCode);
            } else {
                // Handle unexpected status codes
                System.err.println("Unexpected response: " + statusCode);
            }
        } catch (Exception e) {
            // Handle Exceptions
            e.printStackTrace();
        }
    }
}

Explanation

  1. HttpClient: The HttpClient is created using HttpClient.newHttpClient().
  2. HttpRequest: Use HttpRequest.Builder to create and configure an HTTP request.
  3. HttpResponse: The client.send() method sends the request and blocks until the response is received.
  4. Status Code Check: The response provides a status code via response.statusCode(). Different ranges of status codes are handled using conditional blocks.

Common HTTP Status Code Ranges

  • 2xx (Success): The request was successfully processed.
  • 3xx (Redirection): The requested resource has been moved.
  • 4xx (Client Errors): The client made an invalid request or the resource was not found.
    • Example: 404 (Not Found), 401 (Unauthorized)
  • 5xx (Server Errors): The server encountered an error while processing the request.
    • Example: 500 (Internal Server Error), 503 (Service Unavailable)

Advanced Handling

Advanced use cases might involve handling:

  • Headers: Access response or set request headers.
  • Timeouts: Set timeouts for requests.
  • Asynchronous Requests: Use HttpClient.sendAsync() for non-blocking requests.

This approach is the standard way to interact with HTTP codes in Java 11+ using the HttpClient API.