A modern HTTP client in the JDK supporting HTTP/2, WebSocket, and both synchronous and asynchronous requests.
The problem it solved
HttpURLConnection dated from HTTP/1.0, had an awkward API, and had no HTTP/2 support, so almost every project added Apache HttpClient or OkHttp for something the platform should provide.
How you did it before
HttpURLConnection for trivial cases, or a third-party client and its transitive dependencies for anything real.
// Built once and shared — it owns a connection pool and an executor.
var client = java.net.http.HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
System.out.println("version = " + client.version());
System.out.println("timeout = " + client.connectTimeout().orElseThrow());
System.out.println("reusable, so create one per application, not per request");
version = HTTP_2
timeout = PT5S
reusable, so create one per application, not per requestJourney: Incubator in 9 and 10, standard in 11.
Asked as
- Why did the JDK need a new HTTP client?
- How do you make concurrent HTTP calls with the JDK client?
- Is the JDK HttpClient thread-safe and reusable?
Scenario question
A service creates a new HttpClient per request and is running out of file descriptors under load.
What is wrong and how do you fix it?
What a good answer weighs
HttpClient is designed to be created once and shared — it holds a connection pool and an executor. Creating one per request creates a pool per request and leaks the resources. Make it a singleton and configure its timeouts and executor deliberately.