Updated: 2017-04-19 11:46 -0500: Called out the need to use
exactly JDK 1.8.0_121 and why.
I still recommend JSF 2.3 EG member and major Mojarra committer Arjan Tijms' blog post for a feature overview of JSF 2.3, but this post gives a brief look into a feature I consider a key validation of the two Java EE 8 specs to which I contribute: Servlet 4.0 and JSF 2.3. The feature is HTTP/2 Server Push, and it's the biggest new feature in Servlet 4.0 in terms of API impact. This blog post shows how Mojarra 2.3.1-SNAPSHOT uses Servlet 4.0 Server Push and solicits testing of this feature for eventual inclusion in Mojarra 2.3.1, and hopefully into GlassFish 5.0.
The Origin of the Feature
Way back at the beginning of Servlet 4.0 in July 2014, when HTTP/2 itself was not even yet final, the idea of using Server Push for JSF was already apparent. After all, the whole point of the feature, from the HTTP/2 protocol level, is to increase the perceived performance of web pages by allowing the server to start sending the assets of the web page before the browser has even started parsing the web page to discover what assets it needs. (I like to call this the Matthew 6:8 feature of HTTP/2.) Web Frameworks such as JSF are in a great position to automatically leverage this feature because the act of authoring the application causes the page author to explicitly indicate at runtime which assets go with which pages. In other words, JSF users get this feature for free without having to change their app in the least.
The Specification of the Feature
The Servlet Expert Group, in particular Greg Wilkins, has crafted an
easy-to-use way to take advantage of Server Push: simply ask the
API as desired, and then call
push() to initiate sending
the bytes of the resource to the client.
From the JSF side, the use of the feature is not captured in the JavaDoc. Rather, it is in the spec PDF section 2.2.6. This section is a high level overview of what happens in the Render Response phase of the request processing lifecycle. We intentionally left the push requirements very high level to allow maximum latitude in implementation. We also had to specify it well in advance of Servlet 4.0 going final due to scheduling constraints with finishing JSF 2.3.
The Implementation of the Feature
I am very thankful to my co-spec lead Dr. Shing Wai Chan for implementing the GlassFish side of this feature, and Ryan Lubke for implementing the underlying Grizzly support for HTTP/2, including push. Ryan had to do several last minute tweaks to get the implementation this far, and it's not 100% done yet. That's why I'm hoping you'll try it.
On the JSF side, I modified the implementation
ExternalContext.encodeResourceURL() to push the resource
PushBuilder API. Because our tests run Mojarra
against both GlassFish 4.1.1 and GlassFish 5.0 trunk, I had to code it
such that the feature only kicks in if Servlet 4.0 is actually
Testing the Feature
To test the feature, you must first make sure you are using exactly
JDK 1.8.0_121, no more no less. The reason for this precise requirement
is explained in this
the Servlet EG. Then, download the GlassFish nightly from
(from 2017-04-17 or later) and replace the
Once your GlassFish has been patched to have the latest Mojarra, deploy an app that has lots of resources. I suggest the PrimeFaces 6.0 showcase. Once deployed the easiest way to see HTTP/2 in action is to use Chrome with Developer Tools to hit <https://localhost:8181/showcase-6.0/index.xhtml> Note that you have to jump through some extra hoops because Chrome finds it easiest to only support HTTP/2 over TLS.
Once the PrimeFaces is being served over HTTPS to Chrome from your
patched GlassFish 5.0, you can visit the "Compare" widget within the
"Multimedia" section. In another Chrome tab, open up
<chrome://net-internals/#events&q=type:HTTP2_SESSION>. Find the
HTTP2_SESSION item to localhost:8181 in the list and
check the checkbox. Do a find in page for
can see that this image was pushed with server push, as shown next.
You can use find in page to look for other hits
HTTP2_SESSION_RECV_PUSH_PROMISE to see resources being
Clicking over to View->Developer->Developer Tools, click the "Disable cache" checkbox and reload the page. Look at the Waterfall column ta see the impact that push has on page load times. You can see that some of the resources are being delivered before the page even finishes loading.
It is beyond the scope of this article to explore this vital aspect of push, but I hope someone else will do so. After all, what's the point of the feature if it does not make page load times seem faster.
SummaryThis feature is still in SNAPSHOT form. I need testing to verify it works for some more cases. If it causes any trouble at all, we may have to put it behind a
com.sun.faces context-param. Please leave comments here with your findings.