Aug 16, 2013

Demistifying JSF lifecycle

(Mojarra 2.1.25)

17-08-2013: I made the source available, see below

There is two sections of this post. The first part is about how JSF lifecycle works, the second part is about showing events and action invocations on diagrams.

What is a view state?

JSF devs are more or less familiar with the JSF lifecycle. I will just quickly show you how it looks, to refresh your memory.

JSF lifecycle

It took quite long to me to clearly understand what is going on under the hood. Namely, what is restoring the view and why JSF has to set values in the application twice: at Apply request values phase and then at Update model values  phase.

When JSF handles a GET request, it first looks at the xhtml where the request points to. It parses that facelet, traverses every template definition, ui:include and components that can be reached and builds up an in-memory representation of components called the view tree. That is right, it happens on every request, that is why a huge view tree makes the application slower. One solution would be if the view tree was taken from a pool for every request as Rudi Simic suggests in this article: Stateless JSF – high performance, zero per request memory overhead -  http://www.industrieit.com/blog/2011/11/stateless-jsf-high-performance-zero-per-request-memory-overhead/ . It is a great article that teaches a lot of how JSF works.

Saving the view state - When you access a page that contains at least one <h:form>, the view state is saved in the session before the request ends. This in fact is some representation of the current view tree. Using an older, 2.1.2 Mojarra reveals this behavior: the JSESSIONID cookie is only created when you encounter a page that loads either a form or uses a @SessionScoped backing bean. In Mojarra 2.1.25, the JSESSIONID cookie is created regardless. In fact, you see the id of the view state at the end of the forms in a hidden input field.

Restoring the view state - On postback from a JSF form, the view state is restored. Every data of the view tree that has been persisted for this view or facelet, and attached to this view state id, is read  from the session and is used to restore the view tree.

<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="-4005688715831258364:-4133587133831516823" autocomplete="off">

The reason for restoring the previous view tree for POST requests is to make sure every component is in place when applying the request values and updating the model values and calling any component event listeners. At first it's not obvious why this is necessary, but the view tree can change from request to request dynamically, and JSF has to make sure, postback of a form arrives to the same view tree as it saw when left the server.
Suppose that you dynamically add some input fields to a form in the invoke application phase or render response phase. After a postback, you could add them again, but only after apply request values and update model values phase. JSF still has to invoke the setters on the value attribute of those input fields and call any component event listener, therefore it restores those dynamically added components as early as possible. The only thing that you have to know now is that values of <h:input> tags are stored in the view state in the session on the server. So form data in fact is stored in two places: bound to your backing beans, and in the UIComponent representing an input field.

Applying request values - When the view state is restored in the components, then JSF sets the values of the components to the ones that came from the request as POST params. This behavior is the responsibility of the decode() method of the UIComponent's Renderer. For example, if you create your own paginator component that goes to the next page when the request value pagerClientId:page comes, this is the place where you inform your component about the new value.


Updating model values - This late phase is where the site developer first (most of the time) interacts with JSF. This is where the setters of the backing beans are called.

Invoking application - You should be familiar with this phase. As seen in the diagram above, this is where actions and actionListeners are invoked regardless of it is an AJAX request or a full page request.

Rendering the response - JSF calls the encode() method on the ViewRoot that encodes the in-memory view tree representation into an HTML represenation for sending back to the client. Every component is responsible for calling encode() method on their children, practically traversing the tree dfs. Additionally the view state is saved in the session, if there is a form element in the tree.

What happens when?

Next thing that takes much practice is to know when actions, listeners, actionListeners, lifecycle phase listeners, component phase listeners, setters, getters, valueChangeListeners are invoked. I created a very simple ajax form with various bindings to my application: a backing bean, a converter, a validator, component phase listeners and a lifecycle phase listener. The goal is to create a clear view of what get's called and when.
  • red events are from the lifecycle phase listener and show JSF lifecycle before and after events
  • blue events come from the declared component lifecycle phase listeners
  • green events are the ones that are calls to backing beans or custom converters, validators
Of course this is a very simple form and I haven't tested several things. For example when component phase listeners are invoked on the commandbuttons. Or whether or not the PreRenderView listener is invoked when the component is not rendered (probably not). 

I put arrows coming from the xhtml to the events to give you some pivot about which event comes from which declaration.

Sorry about the kinda' bad quality. Click on the links below the images to see them in big.

Sources on github: https://github.com/pkonyves/jsf-lifecycle-explained
Download as ZIP link: https://github.com/pkonyves/jsf-lifecycle-explained/archive/master.zip
Building instructions are in README.md

First page load



When you use <f:viewParam> parameters, the FULL lifecycle is triggered with APPLY_REQUEST_VALUES through INVOKE_APPLICATION phase. That is, because viewParams are implemented as UIInput elements therefore it requires these phases.

Partial ajax request executing only the 'number' input field


render: @all, execute: number -http://i.imgur.com/YurYAYj.png?1

Some remarks:
Value change listeners are invoked before setters and Action listeners are called before actions. This means, when the value change listener gets called, the new value is not set in the backing bean, of course the javax.faces.event.ValueChangeEvent makes it easy to retrieve the old and new values. And not suprisingly value change listeners are only invoked, when the value changed, on the other hands, setters are invoked every time.

All of the pictures were take in one session, and by the object IDs, you can see that the components were recreated on every request. I haven't tested with MyFaces, maybe that is smarter.

Ajax request executing the whole form


render: @all, execute:@form - http://i.imgur.com/7TfTDBn.png?1


1 comment: