The Standardized HTTP Client API in Java SE 11
The new standardized HTTP Client API was initially introduced in Java SE 9, as an incubated module in the jdk.incubator.http package, and later enhanced in Java SE 10. This HTTP Client API was standardized and made available under the java.net.http package in Java 11.
The new HTTP Client API allows a new way to make HTTP requests and retrieve responses. This new API replaces the legacy java.net.HttpURLConnection API.
This is a part of the main article “Java Versions and Programming Language Features”.
Making HTTP Connections before Java SE 11
The legacy java.net.HttpURLConnection had many inherent problems. It inherited java.net.URLConnection which was designed considering many protocols that are now defunct (ftp, gopher, etc.). The legacy java.net.HttpURLConnection is hard to use and has too many undocumented behaviors. The API also predates HTTP/1.1.
The built-in HTTP client library provided very basic functions. Developers hence often resorted to better and stable alternative libraries like Apache HttpClient, Unirest HTTP, and Jersey Client.
Examples of making HTTP Connections
1. A simple GET request
Pre Java 11
try { // The code to actually request starts here... URL url = new URL(GET_URL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); StringBuilder responseBuilder = new StringBuilder(); for(String str; (str = in.readLine()) != null; ){ responseBuilder.append(str); } in.close(); System.out.println(responseBuilder.toString()); // The code to actually request ends here ... } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
Java 11
try { HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder(URI.create(GET_URL)).build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
2. Request Parameters and Headers
Pre Java 11
try { // The code to actually request starts here... URL url = new URL(POST_URL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("POST"); // Adding headers to the request con.setRequestProperty("Content-Type", "application/json"); // Adding HTTP Request Parameters con.setDoOutput(true); DataOutputStream dos = new DataOutputStream(con.getOutputStream()); dos.writeChars("fname=Janeve&lname=George"); dos.flush(); dos.close(); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); StringBuilder responseBuilder = new StringBuilder(); for(String str; (str = in.readLine()) != null; ){ responseBuilder.append(str); } in.close(); System.out.println(responseBuilder.toString()); // The code to actually request ends here ... } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
Java 11
To send the request parameters, you will have to write a utility method to do so. The utility method I am using in this example is HttpRequest.BodyPublisher ofFormData(Map<Object, Object> data) .
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(encode(entry.getKey())); builder.append("="); builder.append(encode(entry.getValue())); } return HttpRequest.BodyPublishers.ofString(builder.toString()); } private static String encode(Object key) { return URLEncoder.encode(key.toString(), StandardCharsets.UTF_8); }
The code to make an HTTP request with the parameters and headers is as shown below.
try { // Adding HTTP Request Parameters Map<Object, Object> data = new HashMap<>(); data.put("fname", "Janeve"); data.put("lname", "George"); HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .POST(ofFormData(data)) .uri(URI.create(POST_URL)) .header("Content-Type", "application/json") // Adding headers to the request .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
3. Configuring Timeouts
Pre Java 11
try { URL url = new URL(GET_URL); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); // Setting the connection and read timeouts con.setConnectTimeout(1000); con.setReadTimeout(1000); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); StringBuilder responseBuilder = new StringBuilder(); for(String str; (str = in.readLine()) != null; ){ responseBuilder.append(str); } in.close(); System.out.println(responseBuilder.toString()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
Java 11
try { HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) // Setting Connection Timeout of 5 Seconds .build(); HttpRequest request = HttpRequest.newBuilder(URI.create(GET_URL)) .timeout(Duration.ofSeconds(5)) // Setting Read Timeout of 5 Seconds .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (IOException | InterruptedException e) { e.printStackTrace(); }
You can find all these examples in my github repository: https://github.com/janevegeorge/java-important-features/tree/master/java-se-11.