#
New HTTP Client in Java
This tutorial explains to you how to use the new HTTP Client in Java. We have an example for you as well.
This feature is introduced in Java 9, but become a standard in Java 11.
Please take a look at the following example and read carefully the comments. The code is self-explanatory.
This example is created from a simple Spring Boot application created with Spring Initializr. I am using Maven, Java 17, Spring Boot 3.1.0.
In order to make the application work, you need to add the json library.
From the base application downloaded from Spring Initializr, I updated the main class as below:
package com.example.demo;
import org.json.JSONObject;
import java.util.function.Function;
public class FindName implements Function<String, String> {
@Override
public String apply(String strIn) {
JSONObject inputJSONOBject = new JSONObject(strIn);
System.out.println("Inside FindName");
return inputJSONOBject.get("name").toString();
}
}
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static java.time.temporal.ChronoUnit.SECONDS;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws IOException, InterruptedException, ExecutionException {
SpringApplication.run(DemoApplication.class, args);
final String url = "https://api.nationalize.io/?name=doru";
//Send SYNC GET request
HttpClient httpClient = HttpClient.newBuilder().build();
HttpRequest httpRequest1 = HttpRequest.newBuilder(URI.create(url))
.version(HttpClient.Version.HTTP_2)
// add a header to the request
.headers("key1", "value1", "key2", "value2")
.header("key3", "value3")
// if you want to add a timeout
.timeout(Duration.of(10, SECONDS))
.GET()
.build();
HttpResponse response1 = httpClient.send(httpRequest1, HttpResponse.BodyHandlers.ofString());
System.out.println("Status code: " + response1.statusCode());
System.out.println("Headers: " + response1.headers()
.allValues("content type"));
System.out.println("Body: " + response1.body());
//Send ASYNC GET request
FindName fn = new FindName();
httpClient.sendAsync(httpRequest1, HttpResponse.BodyHandlers.ofString())
// take the body from the request
.thenApply(HttpResponse::body)
// apply a function to the result returned from the line above
.thenApply(fn)
// print the result returned from the line above
.thenAccept(System.out::println)
// join() waits for the stream to complete
// if not present this thread will run in parallel with the main thread
.join();
System.out.println("END1");
TimeUnit.SECONDS.sleep(5);
System.out.println("END2");
}
}
When I run this code I get the following log:
Status code: 200
Headers: []
Body: {"country":[{"country_id":"RO","probability":0.849},{"country_id":"MD","probability":0.023},{"country_id":"AT","probability":0.011},{"country_id":"IE","probability":0.009},{"country_id":"CY","probability":0.009}],"name":"doru"}
Inside FindName
doru
END1
END2
Process finished with exit code 0
There is a way to add an username/password to the request as well if needed:
HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protectedPasswordAuthenticationgetPasswordAuthentication() {
return new PasswordAuthentication(
"username",
"password".toCharArray());
}
}).build();
There are some options when we want to call a REST API:
for JavaEE (including Spring)
For a Java 11+ application, the choice could be this New HTTP Client. The old HTTP client was using HttpURLConnection class. You have an example of how to use HttpURLConnection here.
There are also some third-party Java HTTP client libraries. We can list some of them: Apache HttpClient which supports synchronous and asynchronous requests, OkHttp which has a lot of helpful built-in features, like automatic handling of GZIP, response caching and retries, Retrofit which is closer to Spring Cloud OpenFeign as logic.
for Spring/ Spring Boot
:
the most used option was RestTemplate class (but starting from Spring 5.0 this class is in maintenance mode). RestTemplate calls are synchronous.
Now, Spring suggests using WebClient instead. Spring WebClient is the latest library provided by Spring to make REST API calls. Spring WebClient calls are synchronous and asynchronous and supports reactive programming. An example you can see here.
Spring Cloud offers also OpenFeign option for calling REST APIs. This method is less verbose and a good choice.