Part 27: Java 11 (LTS) – The Standard HTTP Client API – Modern REST Communication for Enterprise Applications

Introduction

One of the defining characteristics of modern software architecture is communication.

Unlike traditional monolithic applications, today’s enterprise systems consist of dozens or even hundreds of independent microservices.

Consider a simple Order Management System.

                    API Gateway
                         │
        ┌────────────────┼────────────────┐
        ▼                ▼                ▼
 Customer Service   Payment Service   Inventory Service
        │                │                │
        └────────────────┼────────────────┘
                         ▼
                  Notification Service

Every service communicates over HTTP.

A single request may trigger multiple REST API calls before a response is returned to the client.

For many years, Java developers relied on:

  • HttpURLConnection
  • Apache HttpClient
  • OkHttp
  • Jersey Client
  • Spring RestTemplate

Although these libraries worked well, the Java platform itself lacked a modern, standard HTTP client.

Java 11 addressed this gap by introducing the Standard HTTP Client API.

The new client provides:

  • A clean and modern API
  • HTTP/2 support
  • Asynchronous programming
  • WebSocket support
  • Improved performance
  • Better integration with CompletableFuture

Today, it is the recommended HTTP client for modern Java applications that do not depend on framework-specific alternatives.


Learning Objectives

By the end of this article, you will be able to:

  • Understand why Java introduced a new HTTP client.
  • Build synchronous and asynchronous REST clients.
  • Configure headers, authentication, and timeouts.
  • Upload and download files.
  • Integrate with JSON.
  • Use HTTP/2.
  • Apply enterprise best practices.
  • Compare the Java HTTP Client with Spring’s RestTemplate and WebClient.

Before Java 11

For years, developers used HttpURLConnection.

Example:

URL url = new URL(
        "https://api.example.com/customers");

HttpURLConnection connection =
        (HttpURLConnection) url.openConnection();

connection.setRequestMethod("GET");

Simple requests required many lines of code.

Handling:

  • Timeouts
  • Authentication
  • Redirects
  • Error handling
  • Response parsing

quickly became cumbersome.

As applications evolved toward microservices, these limitations became more apparent.


Java 11 Solution

The new API revolves around three core classes:

HttpClient

↓

HttpRequest

↓

HttpResponse

This separation of responsibilities makes the API easier to understand and extend.


Creating an HttpClient

HttpClient client = HttpClient.newHttpClient();

This creates a client with sensible defaults.

For production systems, additional configuration is often desirable.


Custom Client Configuration

HttpClient client =

        HttpClient.newBuilder()

                .connectTimeout(Duration.ofSeconds(10))

                .followRedirects(
                        HttpClient.Redirect.NORMAL)

                .version(HttpClient.Version.HTTP_2)

                .build();

This client:

  • Uses HTTP/2 where supported.
  • Follows redirects.
  • Applies a connection timeout.

Building an HTTP Request

HttpRequest request =

        HttpRequest.newBuilder()

                .uri(
                        URI.create(
                                "https://api.example.com/customers"))

                .GET()

                .build();

Requests are immutable, making them thread-safe and reusable.


Sending a Synchronous Request

HttpResponse<String> response =

        client.send(

                request,

                HttpResponse.BodyHandlers.ofString());

Retrieve the response body:

System.out.println(response.body());

Status code:

response.statusCode();

Headers:

response.headers();

Sending an Asynchronous Request

One of the biggest advantages of the Java 11 client is seamless integration with CompletableFuture.

CompletableFuture<HttpResponse<String>> future =

        client.sendAsync(

                request,

                HttpResponse.BodyHandlers.ofString());

This allows multiple remote services to be called concurrently.


Processing the Response

future.thenApply(HttpResponse::body)

      .thenAccept(System.out::println);

No blocking.

No explicit thread management.


HTTP POST Request

HttpRequest request =

        HttpRequest.newBuilder()

                .uri(
                        URI.create(
                                "https://api.example.com/orders"))

                .header(
                        "Content-Type",
                        "application/json")

                .POST(
                        HttpRequest.BodyPublishers.ofString(json))

                .build();

The API provides body publishers for common payload types.


HTTP PUT Request

.PUT(
        HttpRequest.BodyPublishers.ofString(json))

HTTP DELETE Request

.DELETE()

Adding Headers

.header("Authorization", bearerToken)

.header("Accept", "application/json")

.header("X-Correlation-Id", correlationId)

Enterprise APIs commonly include:

  • Authorization tokens
  • Correlation IDs
  • Tenant identifiers
  • Locale information

Timeout Configuration

HttpRequest request =

        HttpRequest.newBuilder()

                .timeout(Duration.ofSeconds(5))

Always configure sensible timeouts.

Waiting indefinitely for another microservice is rarely acceptable.


File Download

client.send(

        request,

        HttpResponse.BodyHandlers.ofFile(path));

Useful for:

  • Reports
  • Images
  • Documents
  • Data exports

File Upload

HttpRequest.BodyPublishers.ofFile(path)

Suitable for sending binary files.

For multipart uploads, additional handling or libraries may be required depending on the API.


JSON Integration

The HTTP Client does not perform JSON serialization.

Typically:

Object

↓

Jackson

↓

JSON

↓

HTTP Client

Response:

JSON

↓

Jackson

↓

Java Object

This separation keeps the HTTP client lightweight.


Authentication

Basic Authentication:

Authorization

↓

Basic Base64(username:password)

Bearer Tokens:

Authorization

↓

Bearer JWT

The client allows any required headers to be added.


HTTP/2

Unlike HttpURLConnection, the Java 11 client supports HTTP/2.

Benefits include:

  • Multiplexing multiple requests over a single connection.
  • Reduced latency.
  • Improved throughput.
  • Better resource utilization.

When both client and server support HTTP/2, the benefits are realized automatically.


WebSocket Support

Java 11 also introduced a standard WebSocket client.

Example:

HttpClient.newHttpClient()

          .newWebSocketBuilder()

Useful for:

  • Live notifications
  • Trading systems
  • Dashboards
  • Chat applications

Enterprise Example

Suppose an Order Service calls:

Customer Service

Inventory Service

Payment Service

Instead of sequential execution:

Customer

↓

Inventory

↓

Payment

Combine the Java 11 HTTP Client with CompletableFuture:

Customer      Inventory      Payment

        │         │         │
        └─────────┼─────────┘
                  ▼
          Order Summary

This significantly reduces overall response time.


Java HTTP Client vs RestTemplate vs WebClient

FeatureJava HTTP ClientRestTemplateWebClient
Standard JDK API
HTTP/2
Async SupportLimited
Reactive
Spring IntegrationModerateExcellentExcellent
External DependencyNoneSpringSpring

Which should you use?

  • Plain Java application: Java HTTP Client.
  • Spring Boot (blocking): Existing RestTemplate code can continue to work, though it is in maintenance mode.
  • Spring Boot (reactive): WebClient is generally the preferred choice.

Common Mistakes

No Timeout

Never call external services without connection and request timeouts.


Blocking Immediately

Calling:

future.join();

immediately after sendAsync() removes most of the benefits of asynchronous execution.


Creating a New HttpClient for Every Request

HttpClient is designed to be reused.

Creating a single configured instance is generally more efficient.


Ignoring HTTP Status Codes

Always inspect the response status before assuming success.

A successful network call is not necessarily a successful business operation.


Best Practices

✔ Reuse HttpClient instances.

✔ Configure timeouts.

✔ Prefer HTTP/2 when available.

✔ Combine with CompletableFuture for parallel service calls.

✔ Use Jackson for JSON serialization.

✔ Include correlation IDs in outbound requests.

✔ Handle non-success HTTP status codes explicitly.


Interview Questions

Why did Java introduce a new HTTP Client?

To provide a modern, standard HTTP API with HTTP/2, asynchronous programming, WebSocket support, and improved usability.


Is the Java HTTP Client thread-safe?

Yes. A single configured instance can be shared across multiple requests.


What is the benefit of sendAsync()?

It enables non-blocking HTTP requests that integrate naturally with CompletableFuture.


Should Spring Boot applications always use the Java HTTP Client?

Not necessarily. Spring applications often use WebClient (particularly in reactive applications) or continue using existing RestTemplate code where appropriate.


Does the Java HTTP Client perform JSON serialization?

No. JSON serialization and deserialization are typically handled by libraries such as Jackson.


Summary

The Java 11 HTTP Client modernized HTTP communication in the JDK by providing a clean, thread-safe, and feature-rich API. With support for HTTP/2, asynchronous requests, WebSockets, and seamless integration with CompletableFuture, it became an excellent choice for modern Java applications.

For enterprise developers, understanding when to use the standard HTTP Client—and how it compares to framework-specific alternatives such as RestTemplate and WebClient—is an important part of designing efficient, maintainable microservices.


Coming Up Next

Part 28 – Java 11 String API Enhancements – isBlank(), strip(), lines(), repeat(), indent(), and Modern Text Processing

We’ll explore how Java 11 simplified everyday string handling, compare the new APIs with pre-Java 11 approaches, discuss Unicode-aware whitespace handling, and demonstrate practical enterprise use cases in validation, parsing, logging, and REST applications.

Leave a Reply

Your email address will not be published. Required fields are marked *