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

[jsr344-experts] Re: [730-Flows] Return node handling

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Thu, 28 Feb 2013 09:41:35 -0500

Hi

2013/2/27 Edward Burns <edward.burns_at_oracle.com>:
> Hello Volunteers,
>
> Leonardo brought up a great point about flow returns. When performing a
> flow return the destination node must be determined with respect to the
> calling flow.
>
> I asked EG member David Schneider about it and here's what he said:
>
> On 02/25/2013 09:22 PM, Edward Burns wrote:
>
> EB> Let's say we are a few flows deep. Does ADF always allow accessing the
> EB> nav rules of the unbounded task flow, as the target of a return node?
>
>>>>>> David Schneider answered:
>
> DS> Hi Ed,
>
> DS> No, ADF does not consult the unbounded flow unless that's the flow the
> DS> application is returning too. When executing a flow return ADF moves
> DS> back to the previous flow (i.e. the one that called the flow that's
> DS> returning) and attempts to navigate from the flow call node using the
> DS> outcome returned from the flow.
>
> DS> Another thing ADF does is record the last viewId that was displayed in
> DS> the calling flow *before* the flow was called. Then, when returning,
> DS> that viewId is displayed again if and only if navigation from the flow
> DS> call using the returned outcome does not produce a new viewId. That's
> DS> done to ensure a viewId from the now current (top of call stack) flow is
> DS> displayed.
>
> This changebundle does the following:
>
> * It implicit navigation can only "see" pages in the current flow.
>
> * Adds API that allows navigation to happen in the scope of the
> preceding flow, if present.
>
> * Adds API that saves the last displayed viewId of the current flow, as
> the flows are being navigated.
>
> SECTION: API changes
> --------------------
>
> M jsf-api/src/main/java/javax/faces/lifecycle/Lifecycle.java
>
> - Revert revision 11649, which introduced the requirement to call
> FlowHandler.clientWindowTransition() to Lifecycle.attachWindow().
> This is now handled in RestoreViewPhase.
>
> M requestProcessingLifecycle.fm
>
> - In section 2.2.1 RestoreViewPhase, call clientWindowTransition().
>
> M applicationIntegration.fm
>
> - In section 7.4.2.1, Requirements for Explicit Navigation in Faces Flow
> Call Nodes other than ViewNodes, here is the new text regarding return
> nodes.
>
> If the node is a ReturnNode obtain its navigation case and call
> FlowHandler.setReturnMode(true). This enables the navigation to
> proceed with respect to the calling flow's navigation rules, or the
> application's navigation rules if there is no calling flow. Start the
> navigation algorithm over using it as the basis but pass the value of
> the symbolic constant javax.faces.flow.FlowHandler.NULL_FLOW as the
> value of the toFlowDocumentId argument. If this does not yield a
> navigation case, call FlowHandler.getLastDisplayedViewId(), which will
> return the last displayed view id of the calling flow, or null if
> there is no such flow. In a finally block, when the re-invocation of
> the navigation algorithms completes, call
> FlowHandler.setReturnMode(false).
>

I don't get these lines. In theory flowDocumentId to use should be the
parent flow flowDocumentId. So, if the node is a ReturnNode, it should
take the outcome, and try to resolve it under the parent flow and if
it resolves to something else the parent flowDocumentId should be
used. If it founds another ReturnNode it should do the same until
the top. The rules that are on top (not bound to any flow and set
globally) only should be consulted if no parent flow is found, respecting
encapsulation principle.

I still don't see clearly the usefulness of setReturnMode(false). In my
opinion it is an internal condition of the navigation algorithm, so it should
not be on FlowHandler. But maybe this method is suggesting that
we need another class to calculate the next node in a flow given the
current context but without affect that context. Something that can
"simulate" things like enter into a flow or return from a flow and get
the next current flow.

regards,

Leonardo Uribe

>
> M jsf-api/src/main/java/javax/faces/flow/FlowHandler.java
>
> - In getCurrentFlow(), document how return mode works.
>
> + *
> + * <div class="changed_added_2_2">
> + *
> + * <p>If {_at_link #setReturnMode} had been called with {_at_code true} as the
> + * argument before invoking this method, return the preceding flow on
> + * the stack instead of the actual current flow, or {_at_code null} if there
> + * is no preceding flow. Otherwise, return the current flow.</p>
> + *
> + * </div>
>
> - new method getLastDisplayedViewId(),
>
> + * <p class="changed_added_2_2">Return the last displayed viewId for the
> + * current flow, as returned by {_at_link #getCurrentFlow(javax.faces.context.FacesContext)},
> + * or {_at_code null} if there is no current flow.</p>
> + *
> + * @param context the {_at_code FacesContext} for the current request.
> + *
> + * @throws NullPointerException if {_at_code context} is {_at_code null}
> + *
> + * @since 2.2
> + */
> +
> + public abstract String getLastDisplayedViewId(FacesContext context);
>
> - new method setReturnMode(),
>
> + * <p class="changed_added_2_2">Enable the correct handling of navigation
> + * when processing a return node. The default {_at_link javax.faces.application.NavigationHandler}
> + * specification requires calling this method with {_at_code true} before processing
> + * the navigation rules for the flow return, and calling this method with
> + * {_at_code false}, from a {_at_code finally} block, immediately afterward.</p>
> + *
> + * @param context the {_at_code FacesContext} for the current request.
>
> + * @param returnMode the return mode for the current flow.
> + *
> + * @throws NullPointerException if {_at_code context} is {_at_code null}.
> + *
> + * @since 2.2
> + */
> +
> + public abstract void setReturnMode(FacesContext context, boolean returnMode);
> +
>
> - New "toViewId" argument to transition().
>
> + * @param toViewId the viewId of the view being displayed as a result of
> + * this transition. This parameter makes it possible to implement {_at_link #getLastDisplayedViewId}.
> + *
>
> M jsf-api/src/main/java/javax/faces/flow/Flow.java
>
> - Fix spelling error.
>
>
> SECTION: Modified Files
> -----------------------
> M jsf-ri/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java
>
> - Because we need the viewId to invoke FlowHandler.transition(), we now
> need to call clientWindowTransition() from RestoreViewPhase instead of
> Lifecycle.attachWindow().
>
> M jsf-ri/src/main/java/com/sun/faces/lifecycle/LifecycleImpl.java
>
> - No longer call clientWindowTransition().
>
> M jsf-ri/src/main/java/com/sun/faces/application/NavigationHandlerImpl.java
>
> - In getNavigationMap(), return the empty map if we are in a flow but the flow has no
> explicitly defined navigation rules.
>
> - In findImplicitMatch(), make it so the navigation can only "see" views
> within the current flow.
>
> - In both places where return nodes are handled, do the right thing with
> respect to the re-invocation of the navigation rules so they operate
> in the context of the calling flow. Also, do the right thing with
> respect to getLastDisplayedViewId().
>
> M jsf-ri/src/main/java/com/sun/faces/flow/FlowHandlerImpl.java
>
> - Implement API changes
>
> M test/web-profile/flow/basic-multi-page-fdl-in-web-inf/src/test/java/com/sun/faces/test/webprofile/flow/basic_in_web_inf/BasicInWebInfFlowEntryExitIT.java
> M test/web-profile/flow/multi-page-from-jar/app/src/test/java/com/sun/faces/test/webprofile/flow/basic_multi_page_flow_in_jar/BasicMultiPageFlowInJarEntryExitIT.java
> M test/web-profile/flow/basic-multi-page/src/test/java/com/sun/faces/test/webprofile/flow/basic_multi_page/BasicMultiPageFlowEntryExitIT.java
> M test/web-profile/flow/basic_faces_flow_call/src/test/java/com/sun/faces/test/webprofile/flow/basic_faces_flow_call/FlowACallsFlowBIT.java
> M test/web-profile/flow/basic-implicit/src/test/java/com/sun/faces/test/webprofile/flow/basic_implicit/BasicFlowEntryExitIT.java
> D test/web-profile/flow/basic-multi-page-fdl-in-web-inf/src/main/webapp/nonFlow.xhtml
> D test/web-profile/flow/multi-page-from-jar/app/src/main/webapp/nonFlow.xhtml
> D test/web-profile/flow/basic-multi-page/src/main/webapp/nonFlow.xhtml
> D test/web-profile/flow/basic-implicit/src/main/webapp/nonFlow.xhtml
>
> - Test changes.
>
> --