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: Fri, 22 Feb 2013 19:24:47 -0800

>>>>> On Sat, 16 Feb 2013 22:13:11 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:

LU> Hi
LU> Checking in deep the latest spec snapshot and pushing the concepts to its
LU> utmost limits, I have found some clarifications that needs to be done and
LU> that can change some parts in the current spec.

LU> This is important feedback. I know there is plenty of things to do, but my
LU> intention here is ensure the spec is consistent with the proposed API.
LU> Really the spec in general looks very good, but are those details what
LU> ensures compatibility and stability between different implementations of
LU> the spec.

LU> In summary:

LU> 1. The spec wording suggest only view nodes or vdl view identifiers can be
LU> used in from-outcome of a switch case, but that could be insuficient.

It is certainly the intent that any spec node can be navigated to within
a flow graph.

I tried to address this in the Proposed Final Draft Release Candidate 2
(PFDRC2) that I just sent out.

LU> 2. It is necessary to provide a list of the current flows being traversed,
LU> to resolve properly ReturnNode case. Also, ReturnNode should be resolved
LU> taking into account the context, in which it is being resolved.

Yes, indeed.

LU> Now the discussion:

LU> 1.

LU> Let's suppose this faces flow definition:

LU> <faces-flow-definition id="flow1">
LU> <switch id="switch1">
LU> <navigation-case>
LU> <if>#{flowBean.someCondition}</if>
LU> <from-outcome>outcome2</from-outcome>
LU> </navigation-case>
LU> <default-outcome>
LU> <from-outcome>exit</from-outcome>
LU> </default-outcome>
LU> </switch>
LU> <flow-return id="exit">
LU> <navigation-case>
LU> <from-outcome>mainpage</from-outcome>
LU> </navigation-case>
LU> </flow-return>
LU> </faces-flow-definition>
LU> <navigation-rule>
LU> <from-view-id>*</from-view-id>
LU> <navigation-case>
LU> <from-action>flow1</from-action>
LU> <from-outcome>mainpage</from-outcome>
LU> <to-view-id>/mainpageforflow1.xhtml</to-view-id>
LU> </navigation-case>
LU> </navigation-rule>

LU> The idea is inside the flow there is a switch and that switch defines as
LU> default-outcome "exit", which is a return node that ends the flow and
LU> outside there is a global navigation rule that resolve the final page.
LU> The syntax is valid, and in my opinion the user expect that this
LU> definition works.

Yes, correct.

LU> But this is what it says in JSF 2.2 section 7.4.2.1 :

LU> "... If the node is a SwitchNode, iterate over the NavigationCase
LU> instances returned from its getCases() method. For each, one call
LU> getCondition(). If the result is true, let vdl view identifier be the
LU> value of its fromOutcome property. ..."

Thank you for finding this. I was using "vdl view identifier" to be a
stand in, for discussion.

LU> This description excludes in a explicit way that a SwitchCase
LU> fromOutcome or SwitchNode defaultOutcome to point to a flow node, and
LU> the example shows that this feature is very helpful.

Yes, that is indeed the point of the feature. I have changed the
wording in 7.4.2.1 to reflect this explicitly.

LU> The same happens with
LU> MethodCallNode "... If the result is null, let vdl view identifier be
LU> the value of the MethodCallNode's outcome property. ..."

LU> The same thing is described in JSF 2.2 section 7.4.2.2 :

LU> "... let switchCaseFromOutcome be the value of the fromOutcome
LU> property of the NavigationCase returned from the defaultCase
LU> property of the SwitchNode, if any. Synthesize a <navigation-case>
LU> as described below from the current flow, the fromAction and
LU> switchCaseFromOutcome. ..."

You found a legitimate problem here. The only way to leave a flow is by
calling another flow via a flow-call node, or by exiting it via a
flow-return node.

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" a
LU> to a vdl view identifier through a NavigationCase, and the "transition
LU> nodes" must be traversed until found a final "state".

Yes, exactly.

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?

Please take a look at the RC 2 and see if I have adequately addressed
your concerns.

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

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.

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'll address this for the final Release Candidate for PFD.

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.

Thanks,

Ed

--