Servlet 4.0 Features

Introduction

The next version of Java EE will be version 8 and when it is eventually released we will see some very interesting improvements in existing APIs. One of those improvements will be the adaption of HTTP/2 to Servlet technologies.

I often post about Servlet 4.0 on Twitter. Follow me here

Appropriate Abstraction

The Servlet API is well positioned to enable HTTP/2 optimisation and to allow frameworks to leverage server push.

How Might Servlets Expose HTTP /2 Features?

Servlets are the right abstraction for the RFC. You don’t want to have to program frames and streams, so a high level API that hides the network layer would be nice. In the Servlets layer you can do the server push with out doing the low level stuff.

One Request and Multiple Responses

One of the changes in the Servlet API is that in HTTP 1 we had one request and one response. In HTTP /2 this is no longer true. There can be one request and the server may decide to push several resources and then finally it responds with the originally requested page. You have one request and multiple responses at the same time and this is a challenge for the Servlet API.

Server Push

Server push is the most visible of the many improvements in HTTP/2 to appear in the servlet API. All of the new features in HTTP/2, including server push, are aimed at improving the perceived performance of the web browsing experience.

Improved Perceived Browser Performance

Server push is enabled to improved perceived browser performance because servers are in a much better position than clients to know what additional assets (such as images, stylesheets and javascripts) a request might ask for next.

For example, it is possible for servers to know that whenever a browser requests an index.html page, it will then request logo image, a style-sheet and menu javascript, etc. Since servers know this, they can pre-emptively start sending these assets while processing the index.html.

Not a Replacement for Web Sockets

It just allows you to populate the browser cache. It is expect that frameworks that build on Servlets like JSF will use this and we solve this problem using the push builder API.

Typical Journey

The browser requests the index page. The server will notice that it needs the style_1.css and the javaScript_1.js files, so we get a PushBuilder from the HTTP request and set the path to the style_1.css file and invoke push, then we set the path to the javaScript_1.js file and invoke a push again.

typical_journey cropped

Note in this case the css and javascript will return to the client first and then the index returns.

Push Builder from HTTP Request

Simply you get the push builder from the HTTP Request object and set the path to the resource and push.

There are two things to note in this sequence diagram,

  1. the push builder can be reused. In the example I use the push builder to push two resources the CSS file and the JavaScript file.
  2. the second thing is that the index.html is returning to the browser after the push resource.

The reason is that if the index returns before the pushed resources, the browser will analysis it and see that it needs the two resources. It will look in the cache and see that it does not have those resources and it will request them. At this point the browser cache will not be prepopulated. So the pushed resources must be returned first before the index is sent.

Push Promise

One of the frames types mentioned earlier was a RST_STREAM this is how the client can decline a push promise. So if the server pushes a resource and the browser already has it in the cache then rather than let the server send the file it will send an RST_STREAM frame saying that it already has the files file so don’t send it.

PushBuilder

To use server push, obtain a reference to a PushBuilder from an HttpServletRequest, mutate the builder as desired, then call the push() method.

push_builder_code_1

This builds a push request based on the HttpServletRequest from which this builder was obtained

push puilder

This builds a push request based on the HttpServletRequest from which this builder was obtained.

The javax.servlet.http.PushBuilder Class

The push request is constructed with the request method set to GET. Conditional, range, expectation, authorization and request headers are removed. Cookies are only added if the maxAge has not expired. The request header will be set to the request URL and any query string that was present. If either of the headers If-Modified-Since or If-None-Match were present then isConditional() will be set to true.

Only URI path Required

The only required setting is the URI path to be used for the push request. This must be called before every call to push(). If the path includes a query string, the query string will be appended to the existing query string (if any) and no de-duplication will occur.

Paths beginning with ‘/’ are treated as absolute paths. All other paths are treated as relative to the context path of the request used to create this builder instance. The path may include a query string.

The resource is pushed by calling the push() method on the pushBuilder instance.

push_builder_in_servlet

This code snippet pushes the header.jpg image to the client that made this request.

Servlets and ServerPush

This code snippet pushes the header.jpg image to the client that made this request.

pushbuilder_complete_example

Filters and Server Push

A different way of solving this problem is to implement the server push in a filter. Jetty has a PushCacheFilter in the org.eclipse.jetty.servlets package.

pushbuilder_filter

JSF Use Case

One of the most important use cases for the server push is the framework case. It is completely dependent on the server having prior knowledge of the resources that the client will ask for before the client asks for them. the server side web frameworks are in a very good position to take advantage of server push.

So JSF is able to use server push very easily. So every time JSF is going to render a style sheet for example it will call the method encodeResourceURL and this is the entry point and here we can initialize the call the server push.

pushbuilder_jsf

This is how web frame works like JSF will be able to leverage the server push modification. This has not been implemented we will see if this is how they decide to do it or if they come up with another method.

Disable/Reject Server Push

The client can explicitly disabled server push by sending a SETTINGS_ENABLE_PUSH setting value of 0 (zero).

In addition to allowing clients to disable server push with the SETTINGS_ENABLE_PUSH setting, servlet containers must honour a client’s request to not receive a pushed response on a finer grained basis by heeding the CANCEL or REFUSED_STREAM code that references the pushed stream’s stream identifier. One common use of this interaction is when a browser already has the resource in its cache.

I often post about Servlet 4.0 on Twitter. Follow me here

Related Articles

Get an overview of the changes coming in HTTP/2.0 and how these are implemented in Java EE 8. I this article we talk about specification and the support that will be available in Java 9 and JavaEE 8.

The adoption of HTTP/2.0 has stagnated over the last four months. In this new article we show how server providers are not migration to HTTP/2.0.

One of the most important developments in JavaEE 8 and Java 9 will be support for HTTP/2. Tomcat 9 supports HTTP/2 but it must be configured to use TLS. Head on over to Configure Tomcat 9 for HTTP/2 to find out how to add the appropriate configurations.