Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews

Mojarra Implementation of JSF 2 has the following context params:

  • com.sun.faces.numberOfViewsInSession (default is 15)
  • com.sun.faces.numberOfLogicalViews (default is 15)

What is the difference between them? The documentation doesn't speak much about these. My app was having trouble with ViewExpiredException for some pages, but after we bumped these settings to a (much) higher value, we stopped having problems.

My app is a financial, form-heavy, ajax-enabled app (some screens have 50+ inputs, with the option of adding alot more data/inputs via AJAX).

what can be the cause for this behaviour? I understand that the first param defines the number of "pages" that are kept in session, which may be useful for the back button, but my use cases that trigger the ViewExpiredException don't use the back button. What does the second param refer to? If I stay in the same screen but keep adding alot of data via AJAX, does this cause the need of a larger number of logical views for page?

like image 320
Miguel Ping Avatar asked Nov 05 '10 11:11

Miguel Ping


2 Answers

First of all, the Mojarra implementation unintentionally swapped the meaning of those context parameters. So if you have the impression that the description is exactly the other way round than what the literal context parameter name implies, then this is indeed true.


com.sun.faces.numberOfLogicalViews

This is basically GET request based. Every GET request creates a new view in session.

To experiment with it, set it to a value of 3, start a new browser session and open 4 different browser tabs (regardless of the URL; may be same, may be different) in sequence and then go back to the 1st tab and submit the form in there. You will get a ViewExpiredException, because this view has been pushed out from the LRU (Least Recently Used) map for views in session. This will not happen if you opened max 3 tabs.

With the default value of 15, this is a rare real world problem. If your webapp is really designed to be used this way (e.g. a social/community site which invites to being opened in multiple tabs, such as discussion forum or Q&A), then you might consider using client side state saving instead of increasing the default value. With client side state saving, you will never face this exception. An alternative would be to use OmniFaces <o:enableRestorableView> in combination a request scoped bean and request parameters, or a view scoped bean which checks in (post)construct if its own state needs to be restored. Again another alternative is to go stateless with <f:view transient="true">, this way the views are not saved anymore, but you cannot use view scoped beans anymore.

The MyFaces equivalent is org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION which defaults to 20.


com.sun.faces.numberOfViewsInSession

This is basically synchronous (non-ajax!) POST request based. Every synchronous POST request creates a new logical view. They are all stored on basis of a physical view like so Map<PhysicalView, Map<LogicalView, ViewState>>. So, with max 15 physical views and max 15 logical views, you can theoretically have 15*15 = 225 views in session.

To experiment with it, set it to a value of 3, open a view with a synchronous form, submit it 4 times and then press the browser's back button 4 times and then submit the form again. You will get a ViewExpiredException, because this view has been pushed out from the LRU (Least Recently Used) map for logical views. This will not happen if you go back max 3 times and then resubmit it.

Note that ajax submits reuse the same logical view (you can confirm it by seeing exactly the same javax.faces.ViewState value being returned on ajax postbacks). There's no browser's back button support for it anyway. The browser's back button only brings you back to the previous synchronous request, it would therefore not make any sense to store all those ajax postbacks as logical views in session.

With the default value of 15 and the current trend of ajax-only forms and disabled cache on dynamic pages, this is a very rare real world problem. Properly designed forms shouldn't invite to pressing the browser's back button. Instead, they should on successful submit redirect to the target view and on failure just redisplay the same form with validation errors. See for hints also How to navigate in JSF? How to make URL reflect current page (and not previous one). Also, cache is more than often disabled on dynamic pages, so the back button would basically give you a brand new view back. See also Avoid back button on JSF web application. If this is also for your application the case, then you can safely set the value to 1.

MyFaces originally had no equivalent for this, and counted this as a physical view in session as well. In version 2.0.6, org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION was introduced, with a similar purpose, though with a different implementation and by default disabled.


See also:

  • Why JSF saves the state of UI components on server?
  • Should PARTIAL_STATE_SAVING be set to false?
  • javax.faces.application.ViewExpiredException: View could not be restored
  • What is the usefulness of statelessness in JSF?
like image 149
BalusC Avatar answered Oct 05 '22 03:10

BalusC


Just found this on the web: http://oss.org.cn/ossdocs/java/ee/javaeetutorial5/doc/JSFConfigure11.html

This might be helpful:

Logical views are subviews of a top-level view. For example, if you have a page that includes multiple frames then each frame is a logical view. If you have a simple application then the default of 15 views or 15 logical views might be too large. In this case, you should consider reducing the allowable number of views and logical views to conserve memory. Conversely, a more complex application might require more than 15 views or logical views to be saved in a session.

like image 20
tasel Avatar answered Oct 05 '22 03:10

tasel