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

[jsr344-experts] Re: Attention Pivotal/SpringSource folks: Faces Flows and SWF

From: Edward Burns <edward.burns_at_oracle.com>
Date: Tue, 7 Jan 2014 09:31:02 -0800

>>>>> On Mon, 6 Jan 2014 16:06:45 -0500, Leonardo Uribe <lu4242_at_gmail.com> said:

LU> In few words, after reading the answer, I can see there is a
LU> difference between what the API was designed for and what should the
LU> API be capable of. Let's see if we can clarify the different points
LU> of view.

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.

EB> But from the perspective that flows should be analogous to method
EB> invocations this does not make sense.

EB> public void foo() { bar(); }

EB> public void bar() { println("bar"); }

EB> It's not possible for foo() to return without bar() returning first.

LU> The fact is this: global (explicit or implicit) navigation still
LU> works while you are inside a flow, which means even if we model a
LU> flow as something analogous to a method, the user can take different
LU> routes that will lead to the mentioned situation. In other words,
LU> enter into a flow does not disable other forms of navigation in an
LU> application.

The spec has the following intents.

1. The only way to get into a flow is through its start node. Any
attempt to enter a flow will cause its start node to be first traversed.

2. Once you are in a flow, there are exactly three ways to leave it.

  a. traverse one of the flow's return nodes.

  b. traverse one of the flows flow-call nodes.

  c. abandon the flow. This has the side effect of also abandoning all
     flows higher up on the call stack.

LU> I think it is up to the user to allow or deny jump outside a flow and then
LU> go back. The fact that a flow can be modeled with defined entry and exit
LU> points, and that some flows does not allow to jump outside, does not means
LU> that all flows should be bound by that rule.

While the 2.2 spec does not prohibit this sort of thing, Rossen observed
the following:

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.

I replied:

EB> One could argue that such an exception is the right response. The
EB> context is indeed not active. However, if you are not using any
EB> flow scoped data, such an exception would not be thrown, and it
EB> would give the impression that the navigation is supported.

EB> I think we can add some language to the spec to detect these "jump
EB> in" cases.

I continue to believe we should prohibit the jump in and jump out cases.

LU> In conclusion we have found two important points that needs to be handled
LU> in a flow:

LU> - It could be good to inhibit a part of the navigation after enter into
LU> a flow.

Yes, I agree.

LU> - Some flows should not support back button, or if back button is pressed
LU> it should throw ViewExpiredException or something like that.

How about generalizing this? We could imagine some kind of
configuration syntax that allows us to say, throw an exception when page
X is reached via the back button.

[...]

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.

EB> I'm not sure if that's a bug or not, but I want to make it so when
EB> you're in the inner flow, you can not access data from the calling
EB> flow unless it is specifically passed in via parameters.

LU> I think do that goes against simplicity. Suppose this: Flow A has a
LU> bean called FlowABean. Flow B has a bean called FlowBBean. Flow A
LU> call Flow B, so if the user wants to get some information from A,
LU> he/she writes something like this:

LU> @Named
LU> FlowScoped("B")
LU> public class FlowBBean
LU> {

LU> @Inject
LU> private FlowABean flowABean;

LU> /* .... */
LU> }

LU> Shoud that be valid? Yes, why not? If Flow A has an explicit call
LU> node that calls Flow B, it means Flow B is a subflow of Flow A, so
LU> the context from Flow A should be accesible from all beans in Flow
LU> B. Is it useful? Yes, of course. Too useful to ignore it. There are
LU> situations where pass parameters can be important or necessary, but
LU> there are others where flow reusal is not that important and a
LU> simple injection will do it just fine. The important thing here is
LU> use Faces Flow to define boundaries and contexts around those
LU> boundaries. Note I'm not using Faces Flow here to pack all views
LU> related to a flow in a single location.

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.

EB> If you want to enter a flow that is already active, from where are you
EB> entering the flow? If you are in another flow, then you must return
EB> from that flow to get back to the previous flow. If you are not in a
EB> flow, then the previous flow can't be active. I don't understand this one.

LU> The idea is:

LU> 1. Enter into Flow A
LU> 2. Navigate to another page using normal/implicit navigation.
LU> 3. Go back to the point the user enter into Flow A

I assume by "the point the user enters into Flow A" you mean, "the page
that has the button that, when clicked, causes entry to Flow A". Let's
call that page, the "doormat page" because you have to stand on the door
mat in front of the door if you want to enter it. If I'm understanding
you correctly, the current spec intent is to treat the act of navigating
from inside Flow A to the doormat page as abandoning the flow. If
navigating from within a flow to the doormat page does not cause
abandoning the flow, it is a bug.

LU> 4. Click again on the button or link.

LU> It can be done with the current spec, and if it can be done it
LU> should work.

If I'm understanding you correctly, this is a bug.

Ed