The lifecycle of a JSF application refers to the various stages of processing of that application, from its initiation to its conclusion. All applications have lifecycle. During a web application lifecycle, common tasks such as the following are performed:
- Handling incoming requests
- Decoding parameters
- Modifying and saving state
- Rendering web pages to the browser
The JavaServer Faces web application manages lifecycle phases automatically for simple applications or allows you to manage them manually for more complex applications as required. JavaServer Faces applications that use advanced features may require interaction with the lifecycle at certain phases. A clearer understanding of the lifecycle phases is key to creating well-designed components.
Before we continue our analysis on the JavaServer Faces lifecycle, let’s build a new JSF application named Hello2.
The lifecycle of a JavaServer Faces application begins when the client makes an HTTP request for a page and ends when the server responds with the page, translated to HTML.
The lifecycle can be divided into two main phases - execute and render. The execute phase is further divided into sub-phases to support the sophisticated component tree. This structure requires that component data be converted and validated, component events be handled, and component data be propagated to beans in an orderly fashion.
A JavaServer Faces page is represented by a tree of components, called a view. During the lifecycle, the JavAServer Faces implementation must build the view while considering the state saved from a previous submission of the page. When the client requests a page, the JavaServer Faces implementation performs several tasks, such as validating the data input of components in the view and converting input data to types specified on the server side.
The JavaServer Faces implementation performs all these tasks as a series of steps in the JavaServer Faces request-response lifecycle.
**This picture comes from the Oracle online Java EE 7 tutorial**
The request-response lifecycle handles two kinds of requests: initial requests and postbacks. An initial request occurs when a user makes a request for a page for the first time. A postback request occurs when a user submits the form contained on a page that was previously loaded into the browser as a result of executing an initial request.
When the lifecycle handles an initial request, it executes only the Restore View and Render Responses phases, because there is no user input or action to process. Conversely, when the lifecycle handles a postback, it executes all of the phases.
Usually, the first parameter for a JavaServer Faces page comes in from a client, as a result of clicking a link or button component on a JavaServer Faces page. To render a response that is another JavaServer Faces page, the application creates a new view and stores it in the javax.faces.context.FacesContext instance, which represents all of the information associated with processing an incoming request and creating a response. The application then acquires object references needed by the view and calls the FacesContext.renderResponse method, which forces immediate rendering of the view by skipping to the Render Response Phase of the lifecycle.
The JavaServer Faces application lifecyle execute phase contains the following sub-phases:
Restore View Phase
When a request for a JavaServer Faces page is made, usually by an action such as when a link or a button component is clicked, the JavaServer Faces implementation begins the Restore View phase.
During this phase, the JavaServer Faces implementation builds the view of the page, wires event handlers and validators to components in the view, and save the view in the FacesContext instance, which contains all the information needed to process a single request. All the application’s components, event handlers, converters, and validators have access to the FacesContext instance.
If the request for the page is an initial request, the JavaServer Faces implementation creates an empty view during this phase and the lifecycle advances to the Render Response phase, during which the empty view is populated with the components referenced by the tags in the page.
If the request for the page is a postback, a view corresponding to this page already exists in the FacesContext instance. During this phase, the JavaServer Faces implementation restores the view by using the state information saved on the client or the server.
Apply Request Values Phase
After the component tree is restored during a postback request, each component in the tree extracts its new value from the request parameters by using its decode (processDecodes() ) method. The value is then stored locally on each component.
If any decode methods or event listeners have called the renderResponse method on the current FacesContext instance, the JavaServer Faces implementation skips to the Render Response Phase.
If any events have been queued during this phase, the JavaServer Faces implementation broadcasts the events to interested listeners.
At the end of this phase, the components are set to their new values, and messages and events have been queued.
Process Validations Phase
During this phase, the JavaServer Faces implementation processes all validators registered on the components in the tree, by using its validate (processValidators) method. It examines the component attributes that specify the rules for the validation and compares these rules to the local value stored for the component.
If the local value is invalid, or if any conversion fails, the JavaServer Faces implementation adds an error message to the FacesContext instance, and the lifecycle advances directly to the Render Response phase so that the page is rendered again with the error messages displayed. If there were conversion errors from the Apply Request Values phase, the messages for these errors are also displayed.
At this point, if the application needs to be redirect to a different web application resource or generate a response that does not contain any JavaServer Faces component, it can call the FacesContext.responseComplete method.
Update Model Values Phase
After the JavaServer Faces implementation determines that the data is valid, it traverses the component tree and sets the corresponding server-side object properties to the component’s local values. The JavaServer Faces implementation updates only the bean properties pointed at by an input component’s value attribute. If the local data cannot be converted to the types specified by the bean properties, the lifecycle advances directly to the Render Response phase so that the page is re-rendered with errors displayed. This is similar to that happens with validation errors.
At this point, if the application needs to redirect to a different web application resource or generate a response that does not contain any JavaServer Faces components, it can call the FacesContext.responseComplete method.
Invoke Application Phase
During this phase, the JavaServer Faces implementation handles any application-level events, such as submitting a form or linking to another page. Finally, the JavaServer Faces implementation transfers control to the Render Response phase.
Render Response Phase
During this phase, JavaServer Faces builds the view and delegates authority to the appropriate resource for rendering the pages.
If this is an initial request, the components that are presented on the page will be added to the component tree. If this is not an initial request, the components are already added to the three, so they need not be added again.
If the request is a postback and errors were encountered during the Apply Request Values phase, Process Validations phase, or Update Model Values phase, the original page is rendered again during this phase. If the pages contain h:message or h:messages tags, any queued error message are displayed on the page.
After the content of the view is rendered, the state of the response is saved so that subsequent requests can access it. The saved state is available to the Restore View phase.
NOTE: The JavaServer Faces lifecycle spans all of the execute and render processes of an application. It is also possible to process and render only parts of an application, such as a single component. For example, the JavaServer Faces Ajax framework can generate requests containing information on which particular component may be processed and which particular component may be rendered back to the client.
Let’s go back to our simple Hello2 web application and talk about the Cancel button. If you run the application and immediately click on the cancel button you will come across validation errors! This happens because even though you are just clicking the Cancel button with an empty form, it is still handled as a “postback” request. But since the form is empty, validation errors are encountered before the navigation handler can process the “cancel” action event and a response of the same page is rendered back to the client.
The solution is to add an immediate attribute to the Cancel button (or any UICommand component) and its value is set to “true”, it will allow the lifecycle to immediately bypass any validation and navigate back to the index.xhtml page.
In general, setting the immediate attribute to “true” on a UICommand component triggers an action event to be fired immediately during the Apply Request Values phase before the Process Validations phase, so no validation errors are encountered.
Finally, components that implement the EditableValueHolder interface (like an input field) have the option of having their validations and conversions performed immediately during the Apply Request Values phase or during the usual Process Validations phase, depending on the value of the immediate attribute supplied. More important, having the immediate attribute set to “true” allows the component to be updated with a new validated value before entering the Process Validations phase, where the rest of the validations will occur for non-immediate components. This is useful when performing UI-only modifications, such as enabling an input field to be editable without submitting and validating the entire data in the form.
You will notice the required attribute is set to “true”. If the user attempts to leave the field blank while submitting the form, a built-in validation error message will appear exactly in the same location as the