Description

then click the button on the first tab 20x or more -> then click the button on the second tab -> you will get the most beloved ViewExpiredException.

Reason:
oam.SerializedViewCollection drops the saved state for 2. tab from map.

Suggestion:
remove the successfully restored view state from map. This can be done, because each SerializedViewKey is unique over all requests for one HttpSession - see DefaultFaceletsStateManagementHelper.nextViewSequence(FacesContext). Because each request has unique sequence number, we can the "just restored" one remove from the map, because it can never come from client again.

Open question: the previous statement is true except the double submit problem: JAVASERVERFACES_SPEC_PUBLIC-559. In this case, server can process same request (with the same sequence number) twice.

Activity

suggested solution attached; not a final patch, because current codebase contains two same classes SerializedViewCollection:
one in JspStateManagerImpl and one in DefaultFaceletsStateManagementHelper - refactor first?

But anyway: review this problem ASAP please, because this is a real blocker for enterprise apps with more than one widnow!

Martin Kočí
added a comment - 26/Apr/11 20:03 suggested solution attached; not a final patch, because current codebase contains two same classes SerializedViewCollection:
one in JspStateManagerImpl and one in DefaultFaceletsStateManagementHelper - refactor first?
But anyway: review this problem ASAP please, because this is a real blocker for enterprise apps with more than one widnow!

You're right, that's a very big problem. However, only if you use server-side state-saving.

The first idea which popped into my mind was using a window-id (which we also requested for JSF 2.2, see [1]).

Your proposal seems even better to me, but we can't commit it directly in the way you are proposing since we should support the double submit scenarios too. Maybe we could remove it after the next but one view has been restored, meaning that you have three view states 1, 2, 3 and you remove 1 after you restored 3. Just an idea...

However, if we commit something that may cause any side effects from the current (== old) behavior (e.g. no double submit possible), we have to make it configurable. Otherwise the chance is high that we break a lot of existing applications...

Jakob Korherr
added a comment - 27/Apr/11 11:48 You're right, that's a very big problem. However, only if you use server-side state-saving.
The first idea which popped into my mind was using a window-id (which we also requested for JSF 2.2, see [1] ).
Your proposal seems even better to me, but we can't commit it directly in the way you are proposing since we should support the double submit scenarios too. Maybe we could remove it after the next but one view has been restored, meaning that you have three view states 1, 2, 3 and you remove 1 after you restored 3. Just an idea...
However, if we commit something that may cause any side effects from the current (== old) behavior (e.g. no double submit possible), we have to make it configurable. Otherwise the chance is high that we break a lot of existing applications...
[1] http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-949

Another idea: we could provide a way to not limit the serialized view states in the session per quantity (currently 20), but per timeout (e.g. 10 minutes). This would most certainly also solve the problem, right?

Jakob Korherr
added a comment - 27/Apr/11 11:51 Another idea: we could provide a way to not limit the serialized view states in the session per quantity (currently 20), but per timeout (e.g. 10 minutes). This would most certainly also solve the problem, right?

Too bad that sychronizer token for JSF is not specified yet (JAVASERVERFACES_SPEC_PUBLIC-559 has my vote). I think that viewSequence used in myfaces codebase is de-facto token and with we can use it for detection if request with same token is processed or not.

Timeout for saved view: I think that does not solve the problem: user can wait between requests seconds or hours, timeout makes behaviour of app undeterministic.

A new param org.apache.myfaces.REMOVE_RESTORED_VIEW_STATE with default false can solve this problem for now. Applications where double submit problem is solved (for example with Seam UIToken or with AJAX-only requests - ajax has own queue) can set this param to true without side effects.

Martin Kočí
added a comment - 27/Apr/11 20:41 Too bad that sychronizer token for JSF is not specified yet (JAVASERVERFACES_SPEC_PUBLIC-559 has my vote). I think that viewSequence used in myfaces codebase is de-facto token and with we can use it for detection if request with same token is processed or not.
Timeout for saved view: I think that does not solve the problem: user can wait between requests seconds or hours, timeout makes behaviour of app undeterministic.
A new param org.apache.myfaces.REMOVE_RESTORED_VIEW_STATE with default false can solve this problem for now. Applications where double submit problem is solved (for example with Seam UIToken or with AJAX-only requests - ajax has own queue) can set this param to true without side effects.

Sorry for a dumb question; but what is the "double submit" problem. Does it refer to a connection retry in which the server actually receives both requests? I'm seeing the defect mentioned here. I use RichFaces for Ajax and use a4j:poll. The polling window quickly uses up the default 20 saved views on the server and then any other open windows immediately get View Expired. Unfortunately some of my view data is large so I"m avoiding using client side.

Robert M. Gary
added a comment - 04/May/11 21:10 Sorry for a dumb question; but what is the "double submit" problem. Does it refer to a connection retry in which the server actually receives both requests? I'm seeing the defect mentioned here. I use RichFaces for Ajax and use a4j:poll. The polling window quickly uses up the default 20 saved views on the server and then any other open windows immediately get View Expired. Unfortunately some of my view data is large so I"m avoiding using client side.

Martin Kočí
added a comment - 04/May/11 21:35 > double submit: when server processes two or more requests from same client (one DOM instance) to same URL (same view in case of JSF):
<h:form>
<h:commandButton actionListener="#
{invokeLongRunningThread}
" />
<h:form>
<h:commandButton actionListener="#
{invokeSomething}
" />
</h:form>
in this case, second button creates another request/response to the same view, which is currently processing LongRunningThread
Robert, do you have all requests AJAXied? If so you can ignore double submit problem, because ajax has own queue.
Anyway this problem is critical for me too (blocks a product delivery) - I'll look at it asap.