Problem
Unnecessary server round trips are a common cause for slow application performance. Unfortunately application frameworks like JSF(Java Server Faces) are forcing developers to do so. For instance given the following URL processed by a JSF Implementation:
http://localhost/myapplication/customer.faces This shows us a customer edit form. We can navigate to other customers, edit a customer or delete the record. So where are the unnecessary round trips to avoid? Let’s take a closer look what happens in case of a JSF navigation rule to be fired. Given is a h:commandLink on the page causing a HTTP postback:
HTTP postback is fired to the server
During Invoke Application Phase, the action method is called giving an outcome.
The outcome is processed by by the NavigationHandler, selecting the NavigationCase
The new view is parsed
During render response phase, the new HTML view is rendered and send to the browser
This is the standard request-response pattern known from HTTP protocol and the JSF life cycle. But what happens if we mark the navigation case as redirect? Then we will see the following:
HTTP Postback is fired to the server
During Ivoke Application Phase, the action method is called giving an outcome.
The outcome is processed by by the NavigationHandler, selecting the NavigationCase
A redirect is sent to the browser
A HTTP Request is fired to the server with the new URL6. Render response phases is invoked
During render response phase, the new HTML view is rendered and send to the browser
Here there are two server round trips, just to display one new page. This is not good as it slows down the application. But how to avoid?
Solution
Use pretty URLs, so instead of using standard JSF:
http://localhost/myapplication/customer.faces Use URLs like
http://localhost/myapplication/customer/1344 http://localhost/myapplication/customer/4343 http://localhost/myapplication/customer/new This can be easily done by JSF and Frameworks like PrettyFaces with JSF 1.1, JSF 1.2 and also JSF 2.0! Give every customer it’s unique URL. This will generate bookmark-able, user-friendly, search engine parse-able URLs, and even the page refresh problem is no problem anymore. And navigating from one customer to another is pretty easy, as they are just links in the browser. Only one request-response is needed, and not two to get the right URL. Most of the JSF navigation rules will become obsolete.
The key point is to move state holding from backing bean to the URL. So instead storing the id of the current customer in a session scoped backing bean(which will cause problems with multiple opened browser windows), or storing the customer id in a request scoped backing bean and using the t:saveState component from Apache Tomahawk to create a “view scope”, we store the id in the URL and pass it during request processing using PrettyFaces. One nice side effect of this solution is that it makes the application more scalable, as no session stored values are used at all. The problem with JSF 2.0 View Scope or pre JSF 2.0 t:saveState is that it stores the backing bean value in the UIViewRoot, which itself is stored inside the current session. This can be avoiding by just using request scoped backing beans together with pretty URLs, and no session data at all.
Nice, right?
Git revision: 2e692ad