>>>>> On Fri, 20 Dec 2013 16:36:39 -0500, Rossen Stoyanchev <rstoyanchev_at_gopivotal.com> said:
H> Personally, the new Faces Flow is neither good nor bad, but I am
H> bitterly disappointed with it. JSF EG declares it is inspired by ADF
H> Task Flow and Spring Web Flow, but it seems they just copied ADF Task
H> Flow and made it standardized.
EB> Now, if Faces Flows does not represent enough of Spring Web Flow, that
EB> is only a function of the participation of the EG members representing
EB> Spring Web Flow.
RS> Faces Flows does not need to represent, or look like Spring Web Flow. The
RS> user is simply comparing ideas from his own experience with different
RS> projects and that is important to do. The list of items at the end of the
RS> blog post are features that Faces Flow can target in subsequent releases.
RS> This is part of natural evolution.
Yes, that's certainly true.
RS> For me however there are more fundamental questions that may have
RS> played a role in the final conclusion even if not verbalized
RS> clearly.
RS> Specifically the stated design goal of encapsulating the details of a flow
RS> in my mind is not met. It's easier to explain by talking about Web Flow. I
RS> recommend running a sample in addition to this very basic description. I'm
RS> happy to provide further explanations.
RS> In Web Flow there is a single flow definition artifact that encapsulates
RS> all flow navigation rules.
Does that artifact encapsulate all the flows for the entire app?
RS> Those rules are enforced and cannot be bypassed. From a client
RS> perspective that means a flow is represented by a single URL
RS> throughout all steps of the flow (and any sub-flows). It also means
RS> a user cannot just type a URL and jump into the middle of the
RS> flow. It would break the defined navigation rules. This may seem
RS> radical at first but consider that you'd never want to jump into the
RS> middle of a shopping cart checkout process (a typical use case for
RS> using flows). This is quite different from free browsing where the
RS> user should be able to jump to anywhere they want to.
RS> I found major differences in the way Faces Flow worked and raised them
RS> before (see links below).
RS>
https://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2012-03/message/29
RS> Perhaps there are specific cases that motivate including flow
RS> information in Facelet pages but I can't see what they are. It's
RS> worth mentioning them explicitly since putting flow information
RS> (navigation?) in Facelet pages seems contrary to the goal of Task
RS> Flow encapsulation.
Yes, we abandoned this approach. Now it is not possible to put flow
information in Facelet pages.
RS>
https://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2012-11/message/81
RS> One observation is with regards to access to flow scoped data. When
RS> using the provided buttons, everything works as it should, i.e. flow
RS> scoped data is created at the point of entering the flow and
RS> destroyed when the flow is exited. However, it is easy to bypass the
RS> entry and exit points. For example I can go directly to a page
RS> associated with a flow without entering the flow, and if the page
RS> tries to access flow data, the result would be
RS> ContextNotActiveException.
One could argue that such an exception is the right response. The
context is indeed not active. However, if you are not using any flow
scoped data, such an exception would not be thrown, and it would give
the impression that the navigation is supported.
I think we can add some language to the spec to detect these "jump in"
cases.
RS> When flows are defined under the web application's root, I can
RS> easily access their source from a browser which is a security
RS> concern. I can see there is an example that puts the flow definition
RS> under WEB-INF but the pages are still under the web application root
RS> and hence the flow is in two different places. It would be useful to
RS> be able to keep a flow with all its files in a folder under WEB-INF.
I've captured these here.
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1246
RS> It does make it difficult to reason about access to flow data in the
RS> context of an active flow, without an active flow, or of some other
RS> flow.
RS> A second question is about what defines the navigation rules of a
RS> flow? In a number of examples, flow definitions don't contain
RS> navigation rules. Instead command buttons have actions that point to
RS> other pages. This is a convenient convention but the end result is
RS> that the flow definition does not ncapsulate all navigation rules,
RS> nor can it enforce them.
This problem is not specific to flows. Rather, it is a consequence of
implicit navigation, added in JSF 2.0. The design intent of implicit
navigation is to take away ammunition from railsfans that complain that
explicit navigation is too verbose. No-one has complained about the
flexibility of implicit navigation outside of the context of flows.
Perhaps it would be sufficient to add a configuration element to the
flow definition that disables implicit navigation just for that flow?
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1247
RS> For example a shopping cart followed by
RS> shipping options and then payment options must be navigated in that
RS> order. Note that this point relates closely to the previous point
RS> above where a page associated with a flow can be reached directly
RS> without formally entering the flow, i.e. nothing enforces what's
RS> possible in terms of navigation.
We can tighten things up under the work for 1247.
>>>>> On Thu, 19 Dec 2013 07:09:52 -0800, Leonardo Uribe <lu4242_at_gmail.com> said:
LU> Implementing Faces Flow feature for MyFaces, I have found some
LU> observations that I would like to discuss. In fact, I have a list of
LU> things I have seen in JSF 2.2 that we can improve, and that I hope
LU> to discuss in this mailing list in the future.
I hope so too.
LU> The first problem we have and the reason why @FlowScoped does not
LU> look like a full conversation scope (Hantsy's item 4) is there is no
LU> clarification about the relationship between flows.
LU> In few words, there are two cases:
LU> - Two or more independent flows are running at the same time.
LU> - Flow A call flow B, but when the flow A ends, since A was called
LU> from B, B should end too.
But from the perspective that flows should be analogous to method
invocations this does not make sense.
public void foo() { bar(); }
public void bar() { println("bar"); }
It's not possible for foo() to return without bar() returning first.
LU> Support these two concepts are very important because users want
LU> to model everything as a flow, and this is esential to allow better flow
LU> reusal. In MyFaces I did this:
LU> - Take into account an ordered list of the active flows instead the
LU> current flow only in the navigation step.
LU> - If the flow is called using its flow name, it is considered and
LU> independent flow.
LU> - If the flow is called using a call flow node, it is considered a subflow, so
LU> if the parent flow ends, the children ends too.
LU> I don't know if you have seen these examples done by a colleague
LU> at Irian, Michael Kurz:
LU>
https://github.com/jsflive/jsf22-examples
LU> Take a look at the example named jsf22-flows. It is quite easy to modify
LU> it and do some tests. Try enter into a flow, then to another without exit
LU> from the first flow and if you use Mojarra you'll see how some links
LU> are disabled.
I'm not sure if that's a bug or not, but I want to make it so when
you're in the inner flow, you can not access data from the calling
flow unless it is specifically passed in via parameters.
LU> Other typical use case is if the user wants to create a link to enter into
LU> a flow, but the flow is already active. In theory, the flow must be
LU> restarted, but sometimes you want to encode the link to just move
LU> to the start page.
If you want to enter a flow that is already active, from where are you
entering the flow? If you are in another flow, then you must return
from that flow to get back to the previous flow. If you are not in a
flow, then the previous flow can't be active. I don't understand this one.
LU> The other problem is about how FlowHandler.clientWindowTransition(...).
LU> The way how flow navigation using GET is different between MyFaces
LU> and Mojarra, even if both are compatible with the spec. In MyFaces, we
LU> are using a NavigationCase wrapper to override fromOutcome and
LU> toFlowDocumentId:
LU> * Wrapper that helps overriding toFlowDocumentId and fromOutcome, to build
LU> * correctly a navigation case that cause a flow action (enter into a flow
LU> * or return from a flow).
LU> *
LU> * The idea is if is necessary to enter into a flow set fromOutcome as the
LU> * flow id and toFlowDocumentId as the flow document id. If it is a return,
LU> * set fromOutcome as the return node and toFlowDocumentId as
LU> FlowHandler.NULL_FLOW
LU> Later, this will be useful to keep track of the navigation and start/end the
LU> flows properly in FlowHandler.clientWindowTransition(...) This is how I
LU> understood this part:
LU> /**
LU> * There are two basic cases: Enter into a flow and return from a flow.
LU> *
LU> * - FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME : value of
LU> the toFlowDocumentId property
LU> * of the navigation case when enter into a flow OR
LU> FlowHandler.NULL_FLOW when return from a flow.
LU> *
LU> * - FlowHandler.FLOW_ID_REQUEST_PARAM_NAME : value of the
LU> fromOutcome property of the navigation case.
LU> * According to the intention it has multiple options:
LU> *
LU> * 1. It can be a flowId, which means enter into a flow.
LU> * 2. It can be a flow call id, which means enter into a flow.
LU> * 3. It can be a flow return id, which means return from a flow.
LU> * - The javadoc of NavigationCase.getToFlowDocumentId() says this:
LU> * "... If this navigation case represents a flow invocation, this
LU> property is the documentId in
LU> * which the flow whose id is given by the return from
LU> getFromOutcome() is defined. Implementations
LU> * must override this method to return the value defined in the
LU> corresponding application
LU> * configuration resources element. The base implementation
LU> returns the empty string. ..."
LU> *
LU> * This is consistent with the previous interpretation, but we
LU> need to include the case where
LU> * toFlowDocumentId is FlowHandler.NULL_FLOW too, which is derived
LU> implicitly. The key of the trick
LU> * is override fromOutcome / toFlowDocumentId in the navigation
LU> algorithm to indicate when the
LU> * navigation case is entering into a flow or return from a flow.
LU> In that way, it is possible
LU> * to use ConfigurableNavigationHandler.getNavigationCase(...) to
LU> know the "route" using the
LU> * initial fromOutcome given in FLOW_ID_REQUEST_PARAM_NAME.
LU> *
LU> **/
LU> In my opinion, the specification done for this feature is fine, but in
LU> MyFaces land
LU> we have had a hard time doing a proper implementation. I agree there are
LU> things to improve, like everything, but there is nothing we cannot do in JSF
LU> 2.3
LU> or later.
I think you're right that we have some more work to do regarding this
method and the return feature.
LU> Some comments over the suggestions done by Hantsy:
HB> Spring Web Flow provides extended persistence support in the whole flow,
HB> so you never worry about the LazyInitializationException thrown
LU> by Hibernate.
LU> That's CDI responsibility. Nothing to do from JSF side.
HB> Spring Web Flow supports events on enter and exit point in every node.
LU> Use f:viewAction
HB> Spring Web Flow supports Ajax, thus the page fragment can participate
HB> into the flow.
LU> Something we need to think. An use case or example is welcomed.
I think this may come into play regarding pop-up windows that function
as modal dialogs.
HB> Spring Web Flow supports subflows in the main flow, and allow you share
HB> the data state between flows directly, the
LU> inbound-parameter/outbound-parameter in the
HB> Faces Flow is very stupid and ugly.
A formal notion of subflow is probably worth investigating.
LU> Take a look at MyFaces, A @FlowScoped bean from a parent flow can be shared
LU> by the child flow.
That runs counter to the "flows are like methods" idea. If flows are
like methods, then @FlowScoped beans are like local variables. In that
case, it's not possible to access them unless the you are on the same
level of the call stack as where they are defined. In any case, we do
need to specify how visibility is supposed to work.
Ed