Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exit a flow?

Once I've entered a Faces Flow, I want to exit it by going to any page that is not part of the flow.

The problem is that the flow is not destroyed if I go outside, for example via an h:link. Indeed, if I click again on a h:commandButton whose action is the flowId, I go back to the previous flow instead of creating a new flow.

How to exit a flow without having the user to click explicitly on a h:commandButton whose action corresponds to the return node of the flow ? Is it even possible ?

Edit:

Let's take this flow for example (from the JEE 7 samples)

@Produces @FlowDefinition
public Flow defineFlow(@FlowBuilderParameter FlowBuilder flowBuilder) {
    String flowId = "flow1";
    flowBuilder.id("", flowId);
    flowBuilder.viewNode(flowId, "/" + flowId + "/" + flowId + ".xhtml").markAsStartNode();

    flowBuilder.returnNode("taskFlowReturn1").
            fromOutcome("#{flow1Bean.returnValue}");
    flowBuilder.returnNode("goHome").
            fromOutcome("#{flow1Bean.homeValue}");

    flowBuilder.inboundParameter("param1FromFlow2", "#{flowScope.param1Value}");
    flowBuilder.inboundParameter("param2FromFlow2", "#{flowScope.param2Value}");

    flowBuilder.flowCallNode("call2").flowReference("", "flow2").
            outboundParameter("param1FromFlow1", "param1 flow1 value").
            outboundParameter("param2FromFlow1", "param2 flow1 value");

    return flowBuilder.getFlow();
}

The flow will be terminated if the user clicks on

<h:commandButton id="index" value="home" action="goHome" />

or

<h:commandButton id="return" value="return" action="taskFlowReturn1" />

But what if the user clicks on

<h:link outcome="someOutcomeUnrelatedToTheFlow"/>

Or if the user changes the url in the browser, without removing the jfwid? It seems the flow isn't terminated but the user is actually browsing outside of the flow.

That seems a bit odd to me: I can't find any way to exit the flow (and release the backing beans) without a specific action from the user on a commandButton/commandLink.

Btw: I'm testing this on WildFly 8 CR1.

like image 630
thomas.g Avatar asked Nov 01 '22 07:11

thomas.g


1 Answers

You are right. In the current version, the spec requires to navigate using UICommand components to determine if the flow is exited or not. However, this is not sufficient for any decent usage scenario where navigation happens using GET.

Notwithstanding the specs conceptual gap, a solution may be implemented and I expect to see one in upcoming versions of JSF libraries (actually, OmniFaces is a good bet, as BalusC and Arjan focus on fixing stuff that was left out in the spec ;-) ).

Technically speaking, a solution may look like this: The jfwid param is already added when h:linkor h:button is used. So a PhaseListener could be used to end the current flow if a view outside of the flows definition is requested. However, this is just a basic idea and there may be stumbling blocks which I did not consider yet.

So, to provide an answer to your question: Currently the only correct way to exit a flow is to either navigate to an exit node or to use h:commandLinkor h:commandButton for page navigation as this will also end a flow when a view outside of the flows definition is requested.

like image 102
tasel Avatar answered Dec 22 '22 10:12

tasel