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

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

From: Edward Burns <edward.burns_at_oracle.com>
Date: Mon, 25 Feb 2013 15:26:33 -0800

>>>>> 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).

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.

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.

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?

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.

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.

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.

Ed
--