问题
I've got a basic flow example working:
src/main/webapp
|
|- index.xhtml
|- flow1
|- flow1-flow.xml
|- flow1.xhtml
index.xhtml has a simple form that enters the flow with a parameter:
<h:form>
Click to enter flow1
<h:commandButton action="flow1" value="Flow 1">
<f:param name="testInput" value="hi there"/>
</h:commandButton>
</h:form>
flow1.xhtml displays the param and lets you enter a value into flow scope:
<h:form>
Hi this is page 1.
<h:inputText label="Enter something:" value="#{flowScope.testOutput}"/><br/>
Request parameter: #{param['testInput']}<br/>
<h:commandButton action="returnFromFlow1"/>
</h:form>
flow1-flow.xml just defines the return node as "returnFromFlow1" and sets it to /index.xhtml.
This seems to be working. I want to implement post-redirect-get when entering the flow so that the browser address bar stays in sync with the view. So I naturally tried action="flow1?faces-redirect=true". This change prevents the flow from executing.. it simply reloads index.xhtml when the button is clicked.
Then I tried action="flow1/flow1.xhtml?faces-redirect=true". This loads the page and redirects as expected, but the flow is not initialized. When I submit the form in the flow, I get an error about flowScope resolving to null.
Doing a little research, I found a tip to set the "to-flow-document-id" to force it to initialize the flow. So I added to my commandbutton. No change.
Any ideas about how to accomplish this?
回答1:
If the only requirement is that the browser address bar stays in sync with the view, you can simply use <h:button
instead of <h:commandButton
. This works because <h:button
uses Javascript to generate a HTTP GET request to start and navigate to the flow. The ID of the flow has to be specified as value of the outcome
attribute:
index.xhtml:
<h:form>
Click to enter flow1
<h:button outcome="flow1" value="Flow 1">
<f:param name="testInput" value="hi there" />
</h:button>
</h:form>
See also:
- Difference between h:button and h:commandButton
If the requirement is that some checks have to be done before the permission to start the flow is granted, you have to manually initialize and navigate to the flow as follows:
index.xhtml:
<h:form>
Click to enter flow1
<h:commandButton action="#{backingBean.startFlow1()}" value="Flow 1" />
</h:form>
flow1.xhtml:
<h:form>
Hi this is page 1.
<h:inputText label="Enter something:" value="#{flowScope.testOutput}"/><br/>
Request parameter: #{flowScope.testInput}<br/>
<h:commandButton action="returnFromFlow1"/>
</h:form>
BackingBean:
public void startFlow1() {
if (!permissionGranted) {
// show "permission denied"
return;
}
final FacesContext facesContext = FacesContext.getCurrentInstance();
final Application application = facesContext.getApplication();
// get an instance of the flow to start
final String flowId = "flow1";
final FlowHandler flowHandler = application.getFlowHandler();
final Flow targetFlow = flowHandler.getFlow(facesContext,
"", // definingDocumentId (empty if flow is defined in "faces-config.xml")
flowId);
// get the navigation handler and the view ID of the flow
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
final NavigationCase navCase = navHandler.getNavigationCase(facesContext,
null, // fromAction
flowId);
final String toViewId = navCase.getToViewId(facesContext);
// initialize the flow scope
flowHandler.transition(facesContext,
null, // sourceFlow
targetFlow,
null, // outboundCallNode
toViewId); // toViewId
// add the parameter to the flow scope
flowHandler.getCurrentFlowScope()
.put("testInput", "hi there2!");
// navigate to the flow by HTTP GET request
final String outcome = toViewId + "?faces-redirect=true";
navHandler.handleNavigation(facesContext,
null, // from action
outcome);
}
Please note that the parameter can not be added to the button in this case but has to be added to the flow scope instead! Also note that the redirect to the flow has to be done by NavigationHandler#handleNavigation() instead of ExternalContext#redirect() because the flow scope is terminated otherwise!
See also:
- Can a faces flow be started from within a Servlet?
- Programmatically get navigation case from faces-config.xml by outcome
- Omnifaces Faces.redirect loses conversation scope
回答2:
Well, if I'm reading the JSF-2.2 faces-config schema correctly, you should be able to specify a <redirect/>
directive in a faces-config.xml. So using the following, you should able to achieve a redirect:
<navigation-rule>
<from-view-id>/pages/test/test.xhtml</from-view-id>
<navigation-case>
<from-outcome>flow1</from-outcome>
<to-flow-document-id>flow1.xhtml</to-flow-document-id>
<redirect />
</navigation-case>
</navigation-rule>
回答3:
Please run this example i hope it will help you out.
<navigation-rule>
<navigation-case>
<from-outcome>flow1</from-outcome>
<to-view-id>flow1.xhtml</to-view-id>
<redirect></redirect>
</navigation-case>
</navigation-rule>
来源:https://stackoverflow.com/questions/23745606/how-to-enter-a-jsf-2-2-flow-with-faces-redirect