Index Page : Link
Donate : Link
Medium Blog : Link
Applications : Link

What is the purpose of HTTP/2 Client:
By using this new HTTP/2 Client, from Java application, we can send HTTP Request and we can process HTTP Response.

Prior to Java 9, we are using HttpURLConnection class to send HTTP Request and to Process HTTP Response. It is the legacy class which was introduced as the part of JDK 1.1 (1997). There are several problems with this HttpURLConnection class.
Problems with Traditional HttpURLConnection class:
- It is very difficult to use.
- It supports only HTTP/1.1 protocol but not HTTP/2(2015) where
- We can send only one request at a time per TCP Connection, which creates network traffic problems and performance problems.
- It supports only Text data but not binary data
- It works only in Blocking Mode (Synchronous Mode), which creates performance problems.
Because of these problems, slowly developers started using 3rd party Http Clients like Apache Http client and Google Http client etc.
JDK 9 Engineers addresses these issues and introduced a brand new HTTP/2 Client in Java 9.
Advantages of Java 9 HTTP/2 Client:
- It is Lightweight and very easy to use.
- It supports both HTTP/1.1 and HTTP/2.
- It supports both Text data and Binary Data (Streams)
- It can work in both Blocking and Non-Blocking Modes (Synchronous Communication and Asynchronous Communication)
- It provides better performance and Scalability when compared with traditional HttpURLConnection. etc…
Important Components of Java 9 HTTP/2 Client:
In Java 9, HTTP/2 Client provided as incubator module.
Module: jdk.incubator.httpclient
Package: jdk.incubator.http
Mainly 3 important classes are available:
- HttpClient
- HttpRequest
- HttpResponse
Note:
Incubator module is by default not available to our java application. Hence compulsory we should read explicitly by using requires directive.
module demoModule
{
requires jdk.incubator.httpclient;
}
Steps to send Http Request and process Http Response from Java Application:
1. Create HttpClient Object
We can use HttpClient object to send HttpRequest to the web server. We can create HttpClient object by using factory method: newHttpClient()
HttpClient client = HttpClient.newHttpClient();
2. Creation of HttpRequest object:
We can create HttpRequest object as follows:
String url = "https://yourcodeacademy.wordpress.com/category/html/";
HttpRequest req = HttpRequest.newBuilder(new URI(url)).GET().build();
Note:
newBuilder() method returns Builder object.
GET() method sets the request method of this builder to GET.
build() method builds and returns a HttpRequest.
public static HttpRequest.Builder newBuilder(URI uri)
public static HttpRequest.Builder GET()
public abstract HttpRequest build()
3. Send HttpRequest by using HttpClient and get the HttpResponse:
HttpClient contains the following methods:
1. send() to send synchronous request(blocking mode)
2. sendAsync() to send Asynchronous Request(Non Blocking Mode)
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asString());
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asFile(Paths.get("abc.txt")));
Note:
BodyHandler is a functional interface present inside HttpResponse. It can be used to handle body of HttpResponse.
4. Process HttpResponse:
HttpResponse contains the status code, response headers and body

HttpResponse class contains the following methods retrieve data from the response
1. statusCode()
Returns status code of the response
It may be (1XX,2XX,3XX,4XX,5XX)
2. body()
Returns body of the response
3. headers()
Returns header information of the response
Demo Program to send GET Request in Blocking Mode:
demoModule
-- packA
---- Test.java
-- module-info.java
module-info.java
module demoModule
{
requires jdk.incubator.httpclient;
}
Test.java
package packA;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import jdk.incubator.http.HttpHeaders;
import java.net.URI;
import java.util.Map;
import java.util.List;
public class Test
{
public static void main (String... args) throws Exception
{
String url = "https://postman-echo.com/get";
sendGetSyncRequest(url);
}
private static void sendGetSyncRequest(String url) throws Exception
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(new URI(url)).GET().build();
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asString());
processResponse(response);
}
private static void processResponse(HttpResponse response)
{
System.out.println("Status Code:"+response.statusCode());
System.out.println("Response Body:"+response.body());
HttpHeaders header = response.headers();
Map<String,List<String>> map = header.map();
System.out.println("Response Headers");
map.forEach((k,v)->System.out.println("\t"+k+":"+v));
}
}
Output:
D:\CodeFactory>javac --module-source-path src -d out -m demoModule
warning: using incubating module(s): jdk.incubator.httpclient
1 warning
D:\CodeFactory>java --module-path out -m demoModule/packA.Test
WARNING: Using incubator modules: jdk.incubator.httpclient
Status Code:200
Response Body:{
"args": {},
"headers": {
"x-forwarded-proto": "https",
"x-forwarded-port": "443",
"host": "postman-echo.com",
"x-amzn-trace-id": "Root=1-6496e4e7-52fa44c1264da32412a71d7b"
},
"url": "https://postman-echo.com/get"
}
Response Headers
:status:[200]
content-length:[240]
content-type:[application/json; charset=utf-8]
date:[Sat, 24 Jun 2023 12:43:19 GMT]
etag:[W/"f0-ejUlHH9v8mRkiS83Y9BzoU1pUM0"]
set-cookie:[sails.sid=s%3AeKY5NprVFcyqYmKxYFLAIgNk0W4zDMA6.hf9%2BnAshvDFV7g0i569Ro4e1uIR3mIb2EaB%2BDn2r3Y4; Path=/; HttpOnly]
Note:
D:\CodeFactory>java --module-path out -m demoModule/packA.Test
WARNING: Using incubator modules: jdk.incubator.httpclient
Exception in thread "main" java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Getting the above error during execution, tried multiple solutions from the web but does not working.. so copied security folder from C:\Program Files\Java\jdk1.8.0_131\jre\lib\ to C:\Program Files\Java\jdk-9\lib\ and it is working fine.
Writing Http Response body to file abc.html:
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asFile(Paths.get("test.html")));
Paths is a class present in java.nio.file package and hence we need to import java.nio.file.Paths;
demoModule
-- packA
---- Test.java
-- module-info.java
module-info.java
module demoModule
{
requires jdk.incubator.httpclient;
}
Test.java
package packA;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import jdk.incubator.http.HttpHeaders;
import java.net.URI;
import java.util.Map;
import java.util.List;
import java.nio.file.Paths;
public class Test
{
public static void main (String... args) throws Exception
{
String url = "https://yourcodeacademy.wordpress.com/category/html/";
sendGetSyncRequest(url);
}
private static void sendGetSyncRequest(String url) throws Exception
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(new URI(url)).GET().build();
HttpResponse response = client.send(request, HttpResponse.BodyHandler.asFile(Paths.get("test.html")));
processResponse(response);
}
private static void processResponse(HttpResponse response)
{
System.out.println("Status Code : " + response.statusCode());
//System.out.println("Response Body : " + response.body());
HttpHeaders header = response.headers();
Map<String,List<String>> map = header.map();
System.out.println("Response Headers");
map.forEach((k,v) -> System.out.println("\t"+k+":"+v));
}
}
Output:
D:\CodeFactory>javac --module-source-path src -d out -m demoModule
warning: using incubating module(s): jdk.incubator.httpclient
1 warning
D:\CodeFactory>java --module-path out -m demoModule/packA.Test
WARNING: Using incubator modules: jdk.incubator.httpclient
Status Code : 200
Response Headers
:status:[200]
content-type:[text/html; charset=UTF-8]
date:[Sat, 24 Jun 2023 13:38:11 GMT]
host-header:[WordPress.com]
server:[nginx]
strict-transport-security:[max-age=31536000]
vary:[Accept-Encoding, accept, content-type, cookie]
x-ac:[1.bom _dca EXPIRED]
test.html will be created in the current working directory. Open that file to see body of response.
Asynchronous Communication:
In Blocking Mode (Synchronous Mode), Once we send Http Request, we should wait until getting
response. It creates performance problems.
But in Non-Blocking Mode (Asynchronous Mode), we are not required to wait until getting the response. We can continue our execution and later point of time we can use that HttpResponse once it is ready, so that performance of the system will be improved.
HttpClient class contains sendAync() method to send asynchronous request.
CompletableFuture> cf = client.sendAsync(request, HttpResponse.BodyHandler.asString());
CompletableFuture Object can be used to hold HttpResponse in aynchronous communication. This class present in java.util.concurrent package. This class contains isDone() method to check whether processing completed or not.
demoModule
-- packA
---- Test.java
-- module-info.java
module-info.java
module demoModule
{
requires jdk.incubator.httpclient;
}
Test.java
package packA;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import jdk.incubator.http.HttpHeaders;
import java.net.URI;
import java.util.Map;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class Test
{
public static void main (String... args) throws Exception
{
String url = "https://postman-echo.com/get";
sendGetSyncRequest(url);
}
private static void sendGetSyncRequest(String url) throws Exception
{
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(new URI(url)).GET().build();
System.out.println("Sending Asynchronous Request...");
CompletableFuture<HttpResponse<String>> cf = client.sendAsync(request, HttpResponse.BodyHandler.asString());
int count = 0;
while (!cf.isDone())
{
//System.out.println("Processing not dont, doing other activity : " + count++);
}
processResponse(cf.get());
}
private static void processResponse(HttpResponse response)
{
System.out.println("Status Code : " + response.statusCode());
System.out.println("Response Body : " + response.body());
HttpHeaders header = response.headers();
Map<String,List<String>> map = header.map();
System.out.println("Response Headers");
map.forEach((k,v) -> System.out.println("\t"+k+":"+v));
}
}
Output:
D:\CodeFactory>javac --module-source-path src -d out -m demoModule
warning: using incubating module(s): jdk.incubator.httpclient
1 warning
D:\CodeFactory>java --module-path out -m demoModule/packA.Test
WARNING: Using incubator modules: jdk.incubator.httpclient
Sending Asynchronous Request...
Status Code : 200
Response Body : {
"args": {},
"headers": {
"x-forwarded-proto": "https",
"x-forwarded-port": "443",
"host": "postman-echo.com",
"x-amzn-trace-id": "Root=1-6496f6fa-1ede972a52ad5a2f720412a4"
},
"url": "https://postman-echo.com/get"
}
Response Headers
:status:[200]
content-length:[240]
content-type:[application/json; charset=utf-8]
date:[Sat, 24 Jun 2023 14:00:26 GMT]
etag:[W/"f0-x+WMfGy0R8cJ+wzga6oVC+3cKNA"]
set-cookie:[sails.sid=s%3AoM3L1l82_scJI75R73xeMmaM7LAZi45A.atpfXrGO33VaML6iB6AAlt7XrGTscIun2UGgJGXS9Z0; Path=/; HttpOnly]
