-->

Exiting a JSF Flow

2019-08-03 23:08发布

问题:

I'm starting to use JSF Flows, and after reading some examples and the specs, I got it to work.

I'm using the Packaging Flows in Directories method, as described in section 11.4.3.3 of the specification. It seems easier and more in line with the naming conventions already adopted since JSF 2.0.

Bellow is my current directory structure. The flow id is wizard.

I understand that there is a concept of exiting the flow by calling a return node.

You see, by the image above, that I don't have a return node view. It's just a wizard, with a bunch of pages that can be navigated back and forth, with the advantage that my ManagedBean state is maintained.

The problem is, I can navigate to any page in my application, and JSF still maintains the state of that flow. If I come back to any of the Wizard pages, all the information is still there, meaning JSF never dropped the flow scope.

My questions are:

  1. If I have a "finish" commandButton, how do I tell JSF that when the user clicks that button, it should drop the current flow scope?
  2. More importantly, what if I don't have a return node? How do I tell JSF to drop the flow state if the user navigates to any view* outside the flow directory? (by the concept of a "flow", I thought this was already standard behavior)

*Just to be clear, I mean another JSF view (another page within my application). I'm aware it can't do anything if the user triggers a request to a page outside my application or outside the JSF scope.

回答1:

How do I tell JSF to drop the flow state if the user navigates to any view outside the flow directory?

JSF has no way of knowing that you simply redirected to say "http://google.de". The bean will reside in memory until the implementation decides it should be removed due to non-usage. I have a similar problem and all I can think of now is to use some JS-Handler which would trigger some logic in the back-end to end the flow. In general case, there is no way of solving this problem if, say, your browser crashes without being able to execute this JS-code.

If I have a "finish" commandButton, how do I tell JSF that when the user clicks that button, it should drop the current flow scope?

You have to define so called return node(-s). I'll give you an example of my configuration, which successfully ends the flow:

<?xml version="1.0"?>
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
 <application/>

 <flow-definition id="myflow">
    <view id="Page1">
        <vdl-document>/myflow/Page1.xhtml</vdl-document>
    </view>

    <start-node>Page1</start-node>

    <flow-return id="exit">
        <from-outcome>/home.xhtml</from-outcome>
    </flow-return>
</flow-definition>

</faces-config>

You have to make sure your command button returns "exit" in the action attribute. E.g.:

<p:commandButton value="Finish Flow" action="exit"/>

Within the flow, whenever you redirect to some new page via "action" attribute, make sure to append 'faces-redirect=true' to the URL, otherwise , at least in my case I get "No active context" error. E.g. like this:

<p:commandButton value="Next Page" action="Page2.xhtml?faces-redirect=true"/>