jsr344-experts@javaserverfaces-spec-public.java.net

[jsr344-experts] Re: PRD Review and pending issues (SwitchNode from-outcome and mixing everything together)

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Tue, 26 Feb 2013 00:18:23 -0500

Hi

2013/2/25 Edward Burns <edward.burns_at_oracle.com>:
>>>>>> On Sat, 16 Feb 2013 22:13:11 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:
>
>
> LU> The same thing is described in JSF 2.2 section 7.4.2.2 :
>
> LU> "... let switchCaseFromOutcome be the value of the fromOutcome property
> LU> of the NavigationCase returned from the defaultCase property of the SwitchNode,
> LU> if any. Synthesize a <navigation-case> as described below from the current
> LU> flow, the fromAction and switchCaseFromOutcome. ..."
>
> EB> You found a legitimate problem here. The only way to leave a flow is by
> EB> calling another flow via a flow-call node, or by exiting it via a
> EB> flow-return node.
>
> I have fixed this by removing the offending paragraph. This is not in
> the PFD RC2 but will be in the PFD RC3 (which will very likely just be
> the PFD).
>

Ok, thanks Ed.

> LU> and with MethodCallNode :
>
> LU> "... If the result is null, let invokeResult be the value of the
> LU> MethodCallNode's outcome property. Synthesize a <navigation-case> as described
> LU> below from the current Flow, the fromAction, and invokeResult. ..."
>
> LU> In few words SwitchNode/SwitchCase, MethodCallNode, FlowCallNode and
> LU> ReturnNode are nodes that defines "transitions" between pages, but the
> LU> pages are the "states". In that sense, only a ViewNode can "synthesize"
> LU> to a vdl view identifier through a NavigationCase, and the "transition
> LU> nodes" must be traversed until found a final "state".
>
> Well, almost. Strictly speaking, the non-view flow nodes are not
> transitions, but they are traversed immediately. View nodes are the
> only kind of node where the state can stay indefinitely, depending on
> user interaction.
>

Ok

> LU> It is also curious that the use of the flow id in the "from-action" after
> LU> a ReturnNode. There is a mention in JSF 2.2 section 7.4.2.2 related
> LU> to SwitchNode:
>
> LU> "... Treat fromAction as a flow id and ask the FlowHandler for a flow
> LU> under that flow id, passing null as the document id ..."
>
> LU> but the same applies to a ReturnNode, right?
>
> I'm just going to axe the entire 7.4.2.2 section since I think it was a
> hold-over from when I didn't have the explicit flow definition
> completely implemented.
>

Ok

> LU> 2.
>
> LU> Consider the following example
>
> LU> <faces-flow-definition id="mainflow">
> LU> <flow-return id="exit2">
> LU> <navigation-case>
> LU> <from-outcome>exit1</from-outcome>
> LU> </navigation-case>
> LU> </flow-return>
> LU> </faces-flow-definition>
> LU> <faces-flow-definition id="subflow">
> LU> <flow-return id="exit">
> LU> <navigation-case>
> LU> <from-outcome>exit2</from-outcome>
> LU> </navigation-case>
> LU> </flow-return>
> LU> </faces-flow-definition>
>
> LU> And first you have entered in mainflow and then in subflow and now outcome is
> LU> "exit". JSF 2.2 section 7.4.2.1 says this:
>
> LU> "... If the node is a ReturnNode obtain its navigation case and start the
> LU> navigation algorithm over using it as the basis. ..."
>
> LU> The problem is the description of the behavior of ReturnNode in this case is
> LU> insuficient. It is expected ReturnNode to start over again but only if the
> LU> flow was not invoked from another flow. In this case, the context takes
> LU> precedence, and the outcome should be resolved first in "mainflow context"
> LU> and then in the "global context".
>
> Yes, I see what you are saying. Do you have a suggestion on how to
> clarify it?
>

Maybe something like this:

"... If the node is a ReturnNode obtain its navigation case and try to
resolve the
outcome under the context of the outer flow if any. If there is no a parent flow
start the navigation algorithm again using it as the basis ..."

In that way the precedence is given to the parent flow and if no match is found
under that context, it restart the navigation algorithm to see if
there is a global
rule.

> LU> This example also shows that getCurrentFlow() is insuficient, because to
> LU> resolve this properly we need the list of flows actually active. The navigation
> LU> algorithm should be smart enough to apply the outcome according to the context.
> LU> For example, if a navigation case is defined inside "mainflow" instead the
> LU> return node, the algorithm should take into account the navigation rules first
> LU> before try to resolve it globally.
>
> When you are in a flow, you can only access navigation rules defined
> within that flow.
>
> The flows are maintained in a stack, so it should be possible to do the
> right thing.
>

The problem is the behavior of ReturnNode, because in that case, the outcome
should be resolved within the parent flow and with getCurrentFlow() we only have
the top level flow, so there is no way to know if the flow was called
from another
flow.

My suggestion is add a method like this (a better name for the method
is welcomed):

public List<Flow> getFlowStack(FacesContext context)

or create a class called FlowReference with two properties (flowId,
flowDocumentId)
and a method like this:

public List<FlowReference> getFlowStack(FacesContext context)

I like this more because you really want to make FlowReference serializable and
store it into the session, so the other method requires the conversion between
a FlowReference and a Flow.

> LU> This example also suggest that the conditions for call FlowHandler.transition()
> LU> are a little bit more complex that it seems:
>
> LU> "... Call transition() on the FlowHandler, passing the current FacesContext,
> LU> the current UIViewRoot, the new UIViewRoot and the facesFlowCallNode
> LU> corresponding to this faces flow call, if any ..."
>
> I've fixed that. Thanks. At one point the signature had UIViewRoot
> where it now has Flow.
>

Ok

> LU> Note this does not match with the current API:
>
> LU> public abstract void transition(FacesContext context,
> LU> Flow sourceFlow,
> LU> Flow targetFlow,
> LU> FlowCallNode outboundCallNode)
>
> LU> Which in my opinion is correct. By definition it is not possible to call the
> LU> same flow recursively, so the method is ok.
>
> I'll write up a test that shows your nesting scenario to get clarity on
> how to proceed.
>

Ok, I'll keep an eye on any change related to this part. Thanks Ed for your
attention in these details.

regards,

Leonardo Uribe

> Ed
> --