This is the second in a series of articles looking at some of the JDK Enhancement Proposals (JEPS) hoping to make their way into Java 9. Last week we looked at JShell. This week, after looking at the good, the bad and the ugly the focus is on HTTP/2 in JEP 110.
This proposal aims to define a new HTTP client API to replace the legacy
HttpURLConnection API. The new HTTP client API will implement HTTP/2 and Websocket. They will be in the java.httpclient module, and at the time of writing they are integrated into JDK 9.
The main difference between HTTP/1.1 and HTTP/2 is how the data is framed and transported between client and server. HTTP/1.1 relies on a request/response cycle: the request is sent to the client, and the server responds. If there is a lot of data, the page can be slow to load. HTTP/2 allows the server to “push” data: it can send back more data than the client requested. This allows it to prioritise and send the data crucial for loading the webpage first, without waiting for the client to make an additional request.
In addition, with HTTP/2 requests and responses can be multiplexed. This means that multiple responses can be grouped, rather than have to wait for the previous packet to send. HTTP/1.1 only really allows one outstanding request per TCP connection.
What’s wrong with HttpURLConnection?
HttpURLConnection API and its implementation are outdated. First, the superclass
URLConnection API was designed with multiple protocols in mind, most of which are now defunct.
HttpURLConnection only works in blocking mode – one thread per request/response pair. This increases the latency and loading times of webpages. It also increases the risk of head-of-line blocking: where a line of packets is waiting for the first packet to be sent. As a workaround, it became common (or, essential) to open several connections to the server. However the HTTP/1.1 standard recommends strongly that a single-user client should not maintain any more than 2 connections with any server.
See How HTTP/2 Is Changing Web Performance Best Practices for more information.
What to expect from the HTTP/2 Client
There are existing HTTP client APIs and implementations outside Java 9, e.g. Jetty and the Apache HttpClient. However according to JEP 110, they are heavyweight in terms of packages and classes. The goals of JEP 110 are to create a simple and concise API that caters for 80-90% of use cases. According to the JEP: “This probably means a relatively small API footprint (e.g. one or two classes in
java.net) that does not necessarily expose all the capabilities of the protocol”.
The API will support both HTTP/1.1 and HTTP/2. For HTTP/1.1, The client API aims to have performance on a par with the Apache HttpClient library, Netty and Jetty. It aims to have the same or lower memory consumption than the legacy
HttpURLConnection and the Apache HttpClient library, Netty and Jetty.
For HTTP/2, it aims to have better scalability and latency than HTTP/1.1, as well as comparable performance to Apache HttpClient, Netty and Jetty, and lower or the same memory consumption.
It will be lightweight and have several new classes. Some examples are
HttpRequest(a request/response interaction)
HttpRequest.Builder(A builder for HttpRequests,created by calling
HttpRequest.BodyProcessor(creates the request body)
Example request and response
// GET HttpResponse response = HttpRequest .create(new URI("http://www.foo.com")) .headers("Foo", "foovalue", "Bar", "barvalue") .GET() .response(); int statusCode = response.statusCode(); String responseBody = response.body(asString()); // POST response = HttpRequest .create(new URI("http://www.foo.com")) .body(fromString("param1=foo,param2=bar")) .POST() .response();
Example from the Java 9 documentation.
With HTTP/2, the server can return multiple responses (server pushes) to the client request. These are handled using the
The request/response can be synchronous or asynchronous:
- Synchronous: the
responseblocks until the entire request has been sent and the response status code and headers have been received.
responseAsyncsends the request. The response is returned asynchronously, after an immediate
- Multiple asynchronous responses:
multiResponseAsyncsends the request asynchronously. Multiple responses are expected. However it can also be used for single responses (e.g with HTTP/1.1).
WebSockets are not new to Java, and are part of the Java EE 7 standard. JEP 110 enables you to easily set up the WebSocket handshake.
WebSocket is a computer communications protocol. It allows the transmission of data in two directions at the same time across a single TCP connection. They are not a HTTP connection, but use HTTP to bootstrap a WebSocket connection. They do this using an Upgrade Header, which the client uses to indicate that it wants to upgrade to a different protocol.
Text and binary can be sent across the WebSocket, as well as pings. Messages are sent through the
sendX methods and received through
WebSocket.Listener.onX methods asynchronously.
Simone Bordet’s talk HTTP 2 0 & Java: Current Status at Devoxx BE 2015