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

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

From: Edward Burns <edward.burns_at_oracle.com>
Date: Thu, 28 Feb 2013 08:22:15 -0800

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