Main Tutorials

Java 11 HttpClient Examples

Java 11 HttpClient

This article shows you how to use the new Java 11 HttpClient APIs to send HTTP GET/POST requests, and some frequent used examples.


  HttpClient httpClient = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_2)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.yourcompany.com", 80)))
        .authenticator(Authenticator.getDefault())
        .build();

1. Synchronous Example

This example sends a GET request to https://httpbin.org/get, and print out the response header, status code, and body.

HttpClientSynchronous.java

package com.mkyong.java11.jep321;

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class HttpClientSynchronous {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_1_1)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws IOException, InterruptedException {

        HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(URI.create("https://httpbin.org/get"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // print response headers
        HttpHeaders headers = response.headers();
        headers.map().forEach((k, v) -> System.out.println(k + ":" + v));

        // print status code
        System.out.println(response.statusCode());

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

    }

}

Output

Terminal

access-control-allow-credentials:[true]
access-control-allow-origin:[*]
connection:[keep-alive]
content-length:[273]
content-type:[application/json]
date:[Sun, 17 May 2020 08:43:18 GMT]
server:[gunicorn/19.9.0]
200
{
  "args": {},
  "headers": {
    "Content-Length": "0",
    "Host": "httpbin.org",
    "User-Agent": "Java 11 HttpClient Bot",
    "X-Amzn-Trace-Id": "Root=1-5ec0f926-5ae58869cfe7162b7c3147fb"
  },
  "origin": "124.82.107.103",
  "url": "https://httpbin.org/get"
}

2. Asynchronous Example

2.1 HttpClient.sendAsync() to send a GET request asynchronous, it will return a CompletableFuture

HttpClientAsynchronous.java

package com.mkyong.java11.jep321;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.time.Duration;

public class HttpClientAsynchronous {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws Exception {

        HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(URI.create("https://httpbin.org/get"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot")
                .build();

        CompletableFuture<HttpResponse<String>> response =
                httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());

        String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);

        System.out.println(result);

    }

}

Output

Terminal

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "User-Agent": "Java 11 HttpClient Bot",
    "X-Amzn-Trace-Id": "Root=1-5ec0fb51-2c5dcf98167c6418bd555548"
  },
  "origin": "124.82.107.103",
  "url": "https://httpbin.org/get"
}  

3. Custom Executor + Concurrent Requests

3.1 Add a custom executor.


	private final ExecutorService executorService = Executors.newFixedThreadPool(5);

  private final HttpClient httpClient = HttpClient.newBuilder()
          .executor(executorService)
          .build();

3.2 Send multiple concurrent requests asynchronously.

HttpClientCustomExecutor.java

package com.mkyong.java11.jep321;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.time.Duration;

public class HttpClientCustomExecutor {

    // custom executor
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .executor(executorService)
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws Exception {

        List<URI> targets = Arrays.asList(
                new URI("https://httpbin.org/get?name=mkyong1"),
                new URI("https://httpbin.org/get?name=mkyong2"),
                new URI("https://httpbin.org/get?name=mkyong3"));

        List<CompletableFuture<String>> result = targets.stream()
                .map(url -> httpClient.sendAsync(
                        HttpRequest.newBuilder(url)
                                .GET()
                                .setHeader("User-Agent", "Java 11 HttpClient Bot")
                                .build(),
                        HttpResponse.BodyHandlers.ofString())
                        .thenApply(response -> response.body()))
                .collect(Collectors.toList());

        for (CompletableFuture<String> future : result) {
            System.out.println(future.get());
        }

    }

}

Output

Terminal

{
"args": {
  "name": "mkyong1"
},
"headers": {
  "Host": "httpbin.org",
  "User-Agent": "Java 11 HttpClient Bot",
  "X-Amzn-Trace-Id": "Root=1-5ec0fd5e-845e2a5889736f9c5bd38a38"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong1"
}

{
"args": {
  "name": "mkyong2"
},
"headers": {
  "Host": "httpbin.org",
  "User-Agent": "Java 11 HttpClient Bot",
  "X-Amzn-Trace-Id": "Root=1-5ec0fd5e-d365205a75254575c9705ca0"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong2"
}

{
"args": {
  "name": "mkyong3"
},
"headers": {
  "Host": "httpbin.org",
  "User-Agent": "Java 11 HttpClient Bot",
  "X-Amzn-Trace-Id": "Root=1-5ec0fd5e-cd61de10889128921dad6008"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong3"
}

4. POST Form Parameters

4.1 Java 11 HttpClient didn’t provide API for the form data, we have to construct it manually.

HttpClientPostForm.java

package com.mkyong.java11.jep321;

import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

public class HttpClientPostForm {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws IOException, InterruptedException {

        // form parameters
        Map<Object, Object> data = new HashMap<>();
        data.put("username", "abc");
        data.put("password", "123");
        data.put("custom", "secret");
        data.put("ts", System.currentTimeMillis());

        HttpRequest request = HttpRequest.newBuilder()
                .POST(ofFormData(data))
                .uri(URI.create("https://httpbin.org/post"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
                .header("Content-Type", "application/x-www-form-urlencoded")
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // print status code
        System.out.println(response.statusCode());

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

    }

    // Sample: 'password=123&custom=secret&username=abc&ts=1570704369823'
    public static HttpRequest.BodyPublisher ofFormData(Map<Object, Object> data) {
        var builder = new StringBuilder();
        for (Map.Entry<Object, Object> entry : data.entrySet()) {
            if (builder.length() > 0) {
                builder.append("&");
            }
            builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8));
            builder.append("=");
            builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8));
        }
        return HttpRequest.BodyPublishers.ofString(builder.toString());
    }

}

Output

Terminal

200
{
"args": {},
"data": "",
"files": {},
"form": {
  "custom": "secret",
  "password": "123",
  "ts": "1589706608386",
  "username": "abc"
},
"headers": {
  "Content-Length": "56",
  "Content-Type": "application/x-www-form-urlencoded",
  "Host": "httpbin.org",
  "User-Agent": "Java 11 HttpClient Bot",
  "X-Amzn-Trace-Id": "Root=1-5ec0ff71-9f0cc3e2bc88b1c0c9c66a43"
},
"json": null,
"origin": "124.82.107.103",
"url": "https://httpbin.org/post"
}

5. POST JSON

HttpClientPostJSON.java

package com.mkyong.java11.jep321;

import java.io.IOException;
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 HttpClientPostJSON {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws IOException, InterruptedException {

        // json formatted data
        String json = new StringBuilder()
                .append("{")
                .append("\"name\":\"mkyong\",")
                .append("\"notes\":\"hello\"")
                .append("}").toString();

        // add json header
        HttpRequest request = HttpRequest.newBuilder()
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .uri(URI.create("https://httpbin.org/post"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
                .header("Content-Type", "application/json")
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // print status code
        System.out.println(response.statusCode());

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

    }

}

Output

Terminal

200
{
"args": {},
"data": "{\"name\":\"mkyong\",\"notes\":\"hello\"}",
"files": {},
"form": {},
"headers": {
  "Content-Length": "33",
  "Content-Type": "application/json",
  "Host": "httpbin.org",
  "User-Agent": "Java 11 HttpClient Bot",
  "X-Amzn-Trace-Id": "Root=1-5ec0fff9-3f6613c39c502fa5e1b79afa"
},
"json": {
  "name": "mkyong",
  "notes": "hello"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/post"
}

6. Authentication

6.1 Start a simple Spring Security WebApp provides HTTP basic authentication, and test it with the new Java 11 HttpClient APIs

HttpClientAuthentication.java

package com.mkyong.java11.jep321;

import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

// start this https://mkyong.com/spring-boot/spring-rest-spring-security-example/
public class HttpClientAuthentication {

    private static final HttpClient httpClient = HttpClient.newBuilder()
            .authenticator(new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(
                            "user",
                            "password".toCharArray());
                }

            })
            .connectTimeout(Duration.ofSeconds(10))
            .build();

    public static void main(String[] args) throws IOException, InterruptedException {

        HttpRequest request = HttpRequest.newBuilder()
                .GET()
                .uri(URI.create("http://localhost:8080/books"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // print status code
        System.out.println(response.statusCode());

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

    }

}

7. FAQs

7.1 Disabled Redirect.


	private final HttpClient httpClient = HttpClient.newBuilder()
            .followRedirects(HttpClient.Redirect.NEVER)
            .build();

Read this HttpClient.Redirect JavaDoc

7.2 Timeout, 5 seconds.


	private final HttpClient httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(5))
            .build();

7.3 Set a Proxy.


	private final HttpClient httpClient = HttpClient.newBuilder()
            .proxy(ProxySelector.of(new InetSocketAddress("your-company-proxy.com", 8080)))
            .build();

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-11

find jep-321

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
19 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
JACK ABOU
3 years ago

I don’t see any close methods on the client or the request. do we need to close these or not? thanks

Arctic5824
2 years ago
Reply to  JACK ABOU

apparently you dont need to, java should take care of it itsself, feels a bit dodgy but there is no way to close it manually

sivaphani
3 years ago

Can you please share an example how send Windows/NTLM authentication request using Java11 HTTP Client?

Stefan
3 years ago

With request.headers() you get the user added headers.
But how do you intercept the cookies automatically added by CookieManager if you apecify that?

		CookieManager cm = new CookieManager();
		CookieHandler.setDefault(cm);

		HttpClient client = HttpClient.newBuilder().build();

       //..........

      System.out.println("Req headers " + request.headers().toString());        //will show only user added headers (and cookies)

This will automatically add the cookies received from the server and send them in a second request to the same domain.
But how how to check what cookies actually are sent?

Thank you.

Uttam
3 years ago

Do u have any example of uploading file with text messages, I mean a multipart/form data with file upload and other params.

Anton Rustamov
2 years ago
Reply to  Uttam
Jak Ber
3 years ago

You’ve missed to mention that e.g. https://golb.hplar.ch/2019/01/java-11-http-client.html is the source of your used ofFormData function, aren’t you?

Hervelus
5 months ago

Is it fully safe (memory, locks, …) to use HttpClient as a class variable ?

zee
10 months ago

how to add interceptor to this httpClient

John
10 months ago

Thank you for all of these excellent examples. A great starting point for learning the API of the new Java 11 HttpClient.

shivayan mukherjee
1 year ago

can you provide the mockito implementation to mock HttpClient.newBuilder()

John
2 years ago

Any multipart example with body parameters?

Norman
2 years ago

For the “3. Custom Executor + Concurrent Requests”, the main thread won’t exit automatically.
An additional “executorService.shutdownNow()” is required in order terminate the whole process.

mackmack
3 years ago

Thank you very much for your help and your tutorials. You do amazing job!

gbolcer
3 years ago

I have the same http request URL, but I want to use a different json POST for each. Can you do a stream of the jsons or do the http requests have to know the body at instantiation?

                .POST(HttpRequest.BodyPublishers.ofString(json))
Manfred Huber
3 years ago

First – Thank you for this absolutely useful example.
Do you know a nice way to ‘intercept’ calls and add a Bearer Authentication header?
I know I can add headers while creating the HttpRequest Object but that seems kinda ugly to me.
I tried to implement my own Authenticator but that didn’t work as I thought it would.

If you have any idea it would be nice if you could share it.

Cesar
3 years ago

Hello

It’s possible send multiple post concurrent requests asynchronously.

Thanks

Denis
4 years ago

Hello.
I can’t find ready solution for HttpResponse.BodyHandlers.ofString() with receiving length limitation.
It is really needed if it is required to get only first part of very big data.

jlpl
4 years ago

Hello
if i have a list of different Url and do Post with json as body.
what is best approach using a sync or concurrently
that