Once upon a time, using the Java SE (Standard Edition) APIs to do common HTTP operations such as REST API calls might have been described…



Java 11: A New Way to handle HTTP & WebSockets in Java!

by Adrian D. Finlay


Posted on August 10, 2018 at 1:06 PM UTC [-4]


Source: Giphy

Once upon a time, using the Java SE (Standard Edition) APIs to do common HTTP operations such as REST API calls might have been described as unnatural and cumbersome. Java 11 officially changes this. Coming with Java 11, the incubated HTTP APIs from Java 9 are now officially incorporated into the Java SE API. The JDK Enhancement Proposal (JEP) 321 was the JEP behind this effort. Since being integrated into Java 11, the API has seen a few changes. As of Java 11, the API is now fully asynchronous. This article will attempt to show you basic use of the new API by performing a REST API call. We will be using openJDK 11.

The APIs use java.util.concurrent.CompleteableFuture<T> to provide asynchronous, non-blocking request/response behavior allowing for dependent actions. The API used new-style OOP method chaining, like a builder which returns an object that may be affected by the method call.

In addition to the standard documentation, you can learn how to practically apply the CompleteableFuture<T> API below.


The new HTTP APIs can be found in java.net.HTTP.*.

The new APIs provide native support for HTTP 1.1/2, WebSocket. The core classes & interface providing the core functionality include:

  • The HttpClient class, java.net.http.HttpClient
  • The HttpRequest class, java.net.http.HttpRequest
  • The HttpResponse<T> interface, java.net.http.HttpResponse
  • The WebSocket interface, java.net.http.WebSocket


The following are the types in the API:


Classes

  • java.net.http.HttpClient
  • java.net.http.HttpHeaders
  • java.net.http.HttpRequest
  • java.net.http.HttpRequest.BodyPublishers
  • java.net.http.HttpRequest.BodyHandlers
  • java.net.http.HttpRequest.BodySubscribers

Interfaces

  • java.net.http.HttpClient.Builder
  • java.net.http.HttpClient.BodyPublisher
  • java.net.http.HttpRequest.BodyPublisher
  • java.net.http.HttpResponse<T>
  • java.net.http.HttpResponse.BodyHandler<T>
  • java.net.http.HttpResponse.BodySubscriber<T>
  • java.net.http.HttpResponse.PushPromiseHandler<T>
  • java.net.http.HttpResponse.ResponseInfo
  • java.net.http.WebSocket
  • java.net.http.WebSocket.Builder
  • java.net.http.WebSocket.Listener

Enumeration

  • java.net.http.HttpClient.Redirect
  • java.net.http.HttpClient.Version

Exception

  • java.net.http.HttpTimeoutException
  • java.net.http.WebSocketHandshakeException

Pre-Java 11 vs. Java 11: Handling REST API Calls:


Pre-Java 11

Java 11


My Impression

The new API is, semantically, everything you would expect of a Java API in 2018. For a start, it is verbose. Secondly, it is modular. Thirdly, it follows the new OOP style of method chaining (or using builders) to construct objects. Fourthly, it feels more natively HTTP.

Verbosity

The bane and (to some) the valor of java has always been verbosity. In Java, unlike most duck typed languages, it is easier to the eye to induce types and behavior. Java API typically follows a natural approach to naming as one might expect in the real world — it is usually intuitive. In addition, java’s typing semantics are explicit, adding to this verbosity. However, the typical verbosity was reduced in my examples through my frequent use of Java 10’s var. Nevertheless, the API feels a bit verbose.

However, credit must be given to the API writers for allowing the implementation to be as configured or as least configured as desired. The new OOP style has allowed for that. For that matter, it should also be noted that there are many things that one can configure in the HTTP request response cycle. Therefore, a great deal of verbosity is expected.

Modularity

Following the long standing unix tradition, long beloved by the Java community and in line with Java 9 efforts, the API is quite modular. The API is careful split into pieces that offer little to no cruft — one gets what one wants and usually nothing more. In addition, there is little dependency on classes not immediately relevant to the task at hand.

One exception to this rule that could be argued is the creation of a WebSocket. The most straightforward (and API recommended) way to create a WebSocket is to use an instance of WebSocket.Builder. WebSocket.Builder instances are most straightforwardly created by using java.net.http.HttpClient.newWebSocketBuilder(). Once that call has been made, it is typically chained with a call to java.net.WebSocket.Builder.buildAsynce(URI uri, WebSocket.LIstener) to produce a CompleteableFuture<WebSocket> object associated with the WebSocket. The WebSocket may then be retrieved by calling get() on the CompleteableFuture object.

Method Chaining

What I like about designing an API with method chaining as a means to construct objects is that it allows for objects that are as least configured as you would like them to be or as highly configured as you would like them to be. This result can be achieved by way of overloading constructors, of course, but after the object has been created one has to call a setter() method to update or a property on the object. With builders, one may retrieve the modified object all in one call. It plays well into handling things like HTTP, where there are many properties to specify. It would be unwieldy to have to put in a 10 argument constructor list to modify an object. This style has been welcomed by the OOP community at large and is here to stay.

Native HTTP Feel

Lastly, the API feels more native to HTTP. Method names such as body() and headers() are more appropriate ways to name a method than getContent() and getHeaderField(), getHeaderKey(). The old APIs seemed to me to be to abstract and concerned with networking in a general sense as opposed to HTTP. It’s also more intuitive in terms of specifying BodyHandlers, and so on. In the old API, this felt like an unnatural operation, or rather, specifying them felt like incorporating a foreign citizen; The design and use of the API can lead to some unexpected behavior. This is, however, just my impression.

Advantages over HTTPUrlConnection

The advantages that have personally caught my eye over the old API are:

  1. Improved Support for HTTP, HTTP/2
  2. Native HTTP Feel, HTTP is a first class citizen
  3. Asynchronous, Non-Blocking Implementation
  4. New API, works more naturally with modern language features

The Source Code

Click the git logo to obtain the full source code, including examples using WebSockets or click here.

Java 11 HTTP/WebSockets git Repository
Follow @afinlay5 Watch Star Fork Download

Source:
Looney Tunes Ending

Leave a Comment:

View Count: 9,077

Author
Adrian D. Finlay is a passionate engineer who revels at all things code. Adrian mainly tinkers with C++, Java, C#, Python, SQL, HTML5, CSS3, & Scala. Adrian also holds the Oracle Certified Associate in Java SE 8 Programming.
Alternative Publications
  • Hackernoon on Medium: https://bit.ly/JavaHttp2
  • Download this article