Skip to content

Lesson 01 · HTTP with java.net.http

Beyond the 1Z0-830 exam

Since Java 11, the JDK ships a modern HTTP client (java.net.http, JEP 321) — HTTP/2, builders, sync and async. You don't need a third-party library for most calls. It's the foundation under this module's lab and a clean way to talk to any REST service.

Objectives

After this lesson you will be able to:

  • Build and reuse an HttpClient.
  • Construct HttpRequest objects for GET/POST with headers and bodies.
  • Read an HttpResponse — status, headers, and body via BodyHandlers.
  • Choose between synchronous (send) and asynchronous (sendAsync) calls.

The three types

The API is three immutable, builder-based types:

TypeRole
HttpClientthe reusable, thread-safe sender; owns the connection pool
HttpRequestone request — URI, method, headers, body
HttpResponse<T>the result — statusCode(), headers(), body()
java
HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .followRedirects(HttpClient.Redirect.NORMAL)
    .build();

Reuse the client

An HttpClient is immutable and thread-safe — build one and share it. Creating a client per request wastes connections and defeats HTTP/2 multiplexing. (Java 21 adds close()/AutoCloseable for graceful shutdown, but a long-lived client is the norm.)

A synchronous GET

java
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/widgets/1"))
    .header("Accept", "application/json")
    .GET()                                   // GET is also the default
    .build();

HttpResponse<String> res = client.send(request, HttpResponse.BodyHandlers.ofString());
int status = res.statusCode();               // e.g. 200
String body = res.body();                    // the JSON text
  • BodyHandlers decide how the response body is read: ofString(), ofByteArray(), ofLines(), ofFile(path), discarding().
  • BodyPublishers produce the request body: ofString(json), ofFile(path), noBody().

Trap — don't confuse the two

BodyHandlers are for responses; BodyPublishers are for requests. BodyPublishers.ofString sets what you send; BodyHandlers.ofString controls what you receive. Swapping them won't compile, but the names are easy to mix up under exam-style pressure.

A POST with a body

java
HttpRequest post = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/widgets"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"Gizmo\"}"))
    .build();

HttpResponse<String> res = client.send(post, HttpResponse.BodyHandlers.ofString());

PUT(...), DELETE(), and method("PATCH", publisher) round out the verbs. The client does not throw on 4xx/5xx — a 404 is a normal response. You must check statusCode() and act on it (the lab throws on a non-200, rather than silently returning a bogus object).

Asynchronous calls

sendAsync returns a CompletableFuture (Module 07) and never blocks the caller:

java
CompletableFuture<String> bodyFuture = client
    .sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body);          // compose, don't block

Use async when firing many requests concurrently or wiring HTTP into a reactive pipeline. For a single call in a test, synchronous send is simpler and easier to assert on.

SDET note

The lab's ApiClient takes its base URL as a constructor argument. That one move lets the test point it at an in-JVM com.sun.net.httpserver.HttpServer on a random port — a real HTTP round-trip with zero network or Docker — while production points it at the live service. Same dependency injection you saw with the JDBC Connection in Module 16.

Key Takeaways

  • java.net.http gives you three types: HttpClient (reuse it), HttpRequest, HttpResponse<T>.
  • BodyHandlers read responses; BodyPublishers produce request bodies — don't swap them.
  • The client doesn't throw on 4xx/5xx; check statusCode() yourself.
  • send is synchronous; sendAsync returns a CompletableFuture for non-blocking/concurrent calls.
  • Inject the base URL so tests can target a local fake server.

Lesson Quiz

Lesson Quiz · HTTP with java.net.http0 / 5
  1. How should you treat an HttpClient instance?

    • ACreate a new one per request
    • BBuild one and reuse it — it's immutable and thread-safe
    • CSubclass it for each endpoint
    • DClose it after every send
  2. Which reads the RESPONSE body as a String?

    • ABodyPublishers.ofString()
    • BBodyHandlers.ofString()
    • CBodyHandlers.discarding()
    • DHttpResponse.ofString()
  3. What does the client do when the server returns 404?

    • AThrows IOException
    • BReturns a normal HttpResponse with statusCode() == 404 — you must check it
    • CRetries automatically
    • DReturns null
  4. sendAsync(...) returns…

    • AHttpResponse<T>
    • BCompletableFuture<HttpResponse<T>>
    • Cvoid
    • DFuture<String> only
  5. To send a JSON request body you use…

    • ABodyHandlers.ofString(json)
    • BBodyPublishers.ofString(json)
    • Crequest.setBody(json)
    • Dclient.body(json)

Next: JSON Binding. This module's lab is in labs/src/main/java/com/jse21/m17_api/.