My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

miercuri, 4 martie 2015

JSF saving the view state

Commonly, the JSF applications' performance is directly related to CPU memory, serialization/deserialization tasks, and network bandwidth. When these variables start to become the source of headache, or errors of type ViewExpiredException or NotSerializableException occur, it is time to find out about JSF's managing view state feature and how it can be finely tuned to increase the performance. Therefore, further, we will discuss about JSF saving the view state - JSF's partial saving view state feature and JSF saving the view state on server/client.

JSF saving the view state
First, you have to know that JSF saves and restores the view state between requests using the ViewHandler/StateManager API. JSF does this during its lifecycle, the view state is saved in the session (or on the client machine) at the end of a request and is restored at the beginning of a request.
JSF uses this technique because it needs to preserve the views state over the HTTP protocol, which is a stateless protocol. Since JSF is stateful, it needs to save the state of views in order to perform the JSF lifecycle over multiple requests from the same user. Each page has a view state that acts as a ping-pong ball between the client and the server. A view is basically a component tree that may be dynamically changed (altered) during HTTP GET and POST requests. Each request will successfully go through the JSF lifecycle only if the component tree was previously saved and is fully capable to provide the needed information, that is, Faces Servlet succeeds to call the needed view handler implementations to restore or build the view. So, when the component tree is programmatically changed (for example, from backing beans or static components) it can't be successfully recreated from scratch (or rebuilt). The only solution is to use the existing state saved at the Render Response phase. Trying to recreate it from scratch will make the programmatic changes useless, since they would no longer be available.

Note Keep in mind that the component tree is just a hand of UI components hierarchically and logically related. The view state maintains the tree structure and the components state (selected/deselected, enabled/disabled, and so on). Therefore, the component tree contains only references to backing beans properties/actions through EL expressions, and does not store the model values.

JSF partial saving view state
Starting with JSF 2.0, the performance of managing the state was seriously increased by adding the partial state saving feature. Basically, JSF will not save the entire component tree, only a piece of it. Obviously this will require less memory. In other words, this means that instead of saving the entire component tree (the whole view, <html>), now, for every request during restore view, JSF will recreate the entire component tree from scratch and initialize the components from their tag attributes. In this way, JSF will save only the things that are deserved to be saved. These are the things that are susceptible to changes (for example, <h:form>) that cannot be recreated from scratch and/or represent inland details of components. These details are: dynamic (programmatic) changes that alter the component tree, different kinds of values that were determined for some components (usually at first postback), and values that were changed for components but have not been submitted (for example,
moving a slider or checking a checkbox). On the other hand, the things that cannot be changed by the client will not be saved.

Partial state saving and tree visiting
In JSF 2.0, the JSF partial state saving feature raised a question similar to how a JSF implementation should visit all the components in the component tree and ask them for their state (partial)? The answer in JSF 2.1 (and earlier versions) was specific to this implementation: Mojarra used a tree visiting algorithm, while MyFaces used a so-called "facets + children" traversal. But, technically speaking, these two approaches are pretty different, because Mojarra provides a pluggable algorithm, while MyFaces doesn't. Moreover, the Mojarra approach is in context (before children are visited, the parent component can choose to use a context/scope), while the MyFaces approach follows a pointer design. Furthermore, the Mojarra algorithm can visit virtual components. (These kinds of components are obtained by looping components such as UIData) On the other hand, from the saving state perspective, using a context/scope and looping virtual components is not desirable, even if affecting the visiting process can be major and useful. In order to solve this problem, JSF 2.1 offers some hints, which can be considered deprecated starting with JSF 2.2. Starting with JSF 2.2, tree visiting is fully capable of partial state saving; thanks to the StateManagementStrategy.saveView() and StateManagementStrategy.restoreView() methods. These two methods are meant to replace their counterparts from the StateManager class, and their implementations are now mandatory to use the visit API. (A good point to start studying may be the UIComponent.visitTree() method.) As a JSF developer, you will probably never interact with this feature, but for the sake of completeness, it may be good to be aware of it.

JSF saving view state on the server or client
Saving the view state can be accomplished on the server that hosts the application, or on the client machine. We can easily choose between the client and the server by adding the context parameter named javax.faces.STATE_SAVING_METHOD to the web.xml file. The value of this method can be server or client as shown in the following code:

<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>

Starting with JSF 2.2, the values of this context parameter are case insensitive. Saving the state on the server means to save it in a session with a special ID known as the view state ID that refers to the state stored in the server memory. This is sent to the client as the value of a hidden input field named, javax.faces.ViewState. This can be easily tested by running an application which produces the HTML code that contains this field, as shown in the following screenshot:


If the state is saved on the client, JSF stores it as the value of the same hidden input field. This value is a base64 encrypted string representing the serialization of the state:

Specifying where the view state will be saved is a piece of cake, but choosing between saving the view state on a client or on a server can be a difficult choice, because each has its own advantages and disadvantages. Both have a cost, and everybody wants to pay a lower price. Choosing the client will increase network traffic because the serialized state will generate a larger value for the javax.faces.
ViewState input field. Moreover, encoding/decoding the view state and possible trespasser attacks are also important drawbacks of this approach. On the other hand, the server uses less memory because nothing is stored in the session. Moreover, storing the view state on the client will also be a good solution to prevent losing it when the server is down, and to prevent ViewExpiredException that occurs when the session has expired, or when the maximum number of opened views was reached. Saving the state on the server has an opposite effect: the network traffic is lower, the usage of memory by the server increases, and the server failures will result in loss of the state and possible ViewExpiredException instances.

Note Usually, developers prefer to have a lower network traffic and use more memory on the server, because memory is easy to provide to an application server. But this is not a rule; you just have to think what's cheaper for you. Some heavy benchmarks can also provide compelling indications about storing the state on the client or on the server.

In order to make the right choice, do not forget that JSF 2.0 comes, by default, with partial state saving, which will be reflected in a smaller size of the javax.faces.ViewState input field (the state saved on the client) or in less memory needed (the state saved on the server). You can disable partial state saving by adding the following context parameter in web.xml:

<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>

For a simple visual test, you can choose to save the state on the client and run the same application twice: first time, enable partial state saving, and second time, disable it—the result shown in the following screenshot speaks for itself:


Furthermore, in the same application, you can use partial state saving for some views and full state saving for other views. Skip the javax.faces.PARTIAL_STATE_SAVING context parameter and use the javax.faces.FULL_STATE_SAVING_VIEW_IDS context parameter. The value of this context parameter contains a list of view IDs for which the partial state saving will be disabled. The IDs should be comma separated, as shown in the following code (suppose you have three pages: index.xhtml, done.xhtml, and error.xhtml, partial state saving is used only for index.xhtml):

<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/done.xhtml,/error.xhtml</param-value>
</context-param>

Programmatically, you can check if the state is saved on the client as follows:

·         In view/page the code is as follows:
#{facesContext.application.stateManager.isSavingStateInClient(facesContext)}

·         In backing bean, the code is as follows:
FacesContext facesContext = FacesContext.getCurrentInstance();
Application application = facesContext.getApplication();
StateManager stateManager = application.getStateManager();
logger.log(Level.INFO, "Is view state saved on client ? {0}",
stateManager.isSavingStateInClient(facesContext));

You also may be interested in:

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors