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

[jsr344-experts] Re: [730-Flows] OutcomeTarget flow navigation

From: Leonardo Uribe <lu4242_at_gmail.com>
Date: Thu, 28 Feb 2013 14:22:25 -0500

Hi

I have checked again the related parts to OutcomeTarget navigation and
everything looks good but when you think about 2 chained ReturnNode
things start to fail.

Consider this use case:

    <faces-flow-definition id="flow2">
        <flow-return id="exit2">
            <navigation-case>
                <from-outcome>exit1</from-outcome>
            </navigation-case>
        </flow-return>
    </faces-flow-definition>
    <faces-flow-definition id="flow1">
        <flow-return id="exit1">
            <navigation-case>
                <from-outcome>mainpage</from-outcome>
            </navigation-case>
        </flow-return>
    </faces-flow-definition>

Two flows, the user enters in flow1 first and then in flow2, but then
the exit node is triggered. Following the algorithm proposed by
OutcomeTarget navigation, when the final page before exit in flow2
is rendered, getNavigationCase() is called, but the generated link
requires exit from 2 flows. How to synthetize a link for this
navigation? It is not possible becase you are using 2 query
parameters, one for the flowId and other for the flowDocumentId, but
the order is exit from two flows, so there should be two transition
calls activated from FlowHandler.clientWindowTransition().

The problem is getNavigationCase() needs to resolve exit1 outcome
from flow1 context, but getCurrentFlow() will always return flow2.
setReturnMode() doesn't help because what's important here is in
some way the navigation algorithm can know the context and resolve
the flow transitions using that information.

The "natural" way to navigate with GET paradigm is use redirect.
My first intution about OutcomeTarget navigation was generate links
pointing to the same view but using the query parameters as
"commands" to indicate the transitions.

In few words there are two options:

1. From the source view ask for a transition starting from node x.
Example:

http://localhost:8080/flow2/endPage.xhtml?navigateTo=exit&jffi=flow2
(from endPage.xhtml navigate to exit node in flow flow2)

This will cause a redirect to mainpage.xhtml.

2. Syntethize the target page from the link but encode the exit
operations:

http://localhost:8080/mainpage.xhtml?navigateTo=exit?jffid=flow2

Or whatever you can imagine, the important is put something that
activates the navigation, whatever it is.

I like the idea to send a command using a query param, no matter if
we use the start of end page in the link, because in that way we
could have things like a ReturnNode that activates a Switch that
activates a MethodCallNode that activates another ReturnNode and
things will keep working as it works with POST case.

At the end, there are many ways to fix it, but in any case the double
chained ReturnNode must be supported by the algorithm. If it doesn't
work, probably there is something missing.

More that prefer one option or another, I'm thinking about which cases
should work and if the current form of the spec can behave as expected.

regards,

Leonardo Uribe

2013/2/28 Edward Burns <edward.burns_at_oracle.com>:
>>>>>> On Thu, 28 Feb 2013 09:19:56 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:
>
> LU> public List<FlowReference> getFlowStack(FacesContext context)
>
> LU> I like this more because you really want to make FlowReference
> LU> serializable and store it into the session, so the other method
> LU> requires the conversion between a FlowReference and a Flow.
>
> EB> I really didn't want to expose the whole flow stack. Instead, I went
> EB> with a modal solution, which is ok because the modality is contained to
> EB> the current client window, so even though the method is on the singleton
> EB> FlowHandler, the behavior is entirely taken from whatever the
> EB> current flow stack is.
> EB>
>
> LU> Use a modal solution is not going to work, because in GET case,
> LU> h:link and h:button call getNavigationCase() and that method should
> LU> do the calculation of the navigation taking into account the current
> LU> context but without affect it. I also don't see how setResetMode()
> LU> logic could work, but I'll comment that part in the Return Node
> LU> mail.
>
> I was able to get it to work pretty cleanly, but I'm sure your
> additional insights can make it better. Let me describe how it is
> currently designed.
>
> First we need to disect the two kinds of navigation in JSF.
>
> A. POSTback navigation
>
> POSTback navigation takes place entirely during the InvokeApplication
> phase. This is all cleanly encapsulated within the
> NavigationHandler.handleNavigation() method. In this case, whenever we
> are dealing with a return node, we call setReturnMode(true) before doing
> any calculations that should be done with respect to that return node.
>
> B. OutcomeTagret navigation
>
> OutcomeTarget navigation (h:link and h:button) takes place in two
> places.
>
> 1. Rendering, where the navigation that would be taken is baked into
> the markup of the component. See the RenderKit specification for
> OutcomeTarget Button. [1] In particular, because OutcomeTarget was
> *already* calling NavigationHandler.getNavigationCase() the
> additional call to setReturnNode() is handled within there. I
> believe this is clear from the text of FlowHandler.setReturnMode() [5]
>
> Enable the correct handling of navigation when processing a
> return node. The default NavigationHandler specification requires
> calling this method with true before processing the navigation
> rules for the flow return, and calling this method with false,
> from a finally block, immediately afterward.
>
> I can add text to NavigationHandler.getNavigationCase(), but I
> think it is unnecessary because the logic in the default navigation
> handler algorithm does include calling setReturnMode(). I'll be
> sharing the PFD with the expert group here today so you can see it
> in context.
>
> 2. On processing the GET request that is sent when the OutcomeTarget
> component is selected. This happens in the new
> FlowHandler.clientWindowTransition(). Originally, I had this being
> called from Lifecycle.attachWindow() [2], but your observations
> regarding return node handling had me move it to
> RestoreViewPhase. [3]
>
>>>>>> On Wed, 27 Feb 2013 05:30:59 -0800, Edward Burns <edward.burns_at_oracle.com> said:
>
> EB> M jsf-api/src/main/java/javax/faces/lifecycle/Lifecycle.java
>
> EB> - Revert revision 11649, which introduced the requirement to call
> EB> FlowHandler.clientWindowTransition() to Lifecycle.attachWindow().
> EB> This is now handled in RestoreViewPhase.
>
> EB> M requestProcessingLifecycle.fm
>
> EB> - In section 2.2.1 RestoreViewPhase, call clientWindowTransition().
>
> LU> Maybe we need a new class that encapsulates the current context but
> LU> only for calculate the navigation (FlowCalculation? or
> LU> FlowCalculator? FlowCalculatorResolver?).
>
> LU> Other solution to fix the GET case could be do not call
> LU> getNavigationCase() at all
> LU> and create a link using the current viewId + flow parameters.
>
> I believe the current design is simpler and has fewer moving parts.
> Please consider carefully if you really want to suggest yet more API on
> this already complex subsystem.
>
> I've taken our test driven development test for this, which does work
> with the current Mojarra, and stripped out any dependencies on our test
> system, making a self contained war for your inspection at [4]. Please
> take a look at it. If you want to run it, just drop the latest
> org.glassfish:javax.faces:2.2.0-SNAPSHOT jar from maven.java.net into
> the modules directory of GlassFish 3.1.2.2.
>
> Please take another look at the current arrangement let me know what you
> think.
>
> Thanks,
>
> Ed
>
> --
>
>
> [1] https://maven.java.net/service/local/repositories/snapshots/archive/javax/faces/javax.faces-api/2.2-SNAPSHOT/javax.faces-api-2.2-20130228.084148-154-javadoc.jar/!/renderkitdocs/HTML_BASIC/javax.faces.OutcomeTargetjavax.faces.Button.html
>
> [2] http://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2013-02/message/68
>
> [3] http://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2013-02/message/69
>
> [4] http://java.net/projects/javaserverfaces-spec-public/downloads/download/JSF_2_2/scratch/basic_faces_flow_call_for_leonardo.zip
>
> [5] https://maven.java.net/service/local/repositories/snapshots/archive/javax/faces/javax.faces-api/2.2-SNAPSHOT/javax.faces-api-2.2-20130228.084148-154-javadoc.jar/!/javadocs/javax/faces/flow/FlowHandler.html#setReturnMode%28javax.faces.context.FacesContext,%20boolean%29
>