jsf - sesiones - primefaces mvc
Cómo ingresar un flujo JSF 2.2 con redirección de rostros (3)
Tengo un ejemplo de flujo básico trabajando:
src/main/webapp
|
|- index.xhtml
|- flow1
|- flow1-flow.xml
|- flow1.xhtml
index.xhtml tiene un formulario simple que ingresa al flujo con un parámetro:
<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 muestra el parámetro y te permite ingresar un valor en el alcance del flujo:
<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 solo define el nodo de retorno como "returnFromFlow1" y lo establece en /index.xhtml.
Esto parece estar funcionando. Quiero implementar post-redirect-get al ingresar el flujo para que la barra de direcciones del navegador permanezca sincronizada con la vista. Entonces, naturalmente, intenté action = "flow1? Faces-redirect = true". Este cambio impide que se ejecute el flujo ... simplemente recarga index.xhtml cuando se hace clic en el botón.
Entonces probé action = "flow1 / flow1.xhtml? Faces-redirect = true". Esto carga la página y redirige como se esperaba, pero el flujo no se inicializa. Cuando envío el formulario en el flujo, recibo un error sobre la resolución de FlowScope a nulo.
Investigando un poco, encontré un consejo para configurar el "to-flow-document-id" para forzarlo a inicializar el flujo. Así que agregué a mi botón de comando. Ningún cambio.
¿Alguna idea sobre cómo lograr esto?
Bueno, si estoy leyendo correctamente el esquema faces-config de JSF-2.2 , debería poder especificar una directiva <redirect/>
en un faces-config.xml . Entonces, usando lo siguiente, deberías poder lograr una redirección:
<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>
Ejecute este ejemplo, espero que lo ayude.
<navigation-rule>
<navigation-case>
<from-outcome>flow1</from-outcome>
<to-view-id>flow1.xhtml</to-view-id>
<redirect></redirect>
</navigation-case>
</navigation-rule>
Si el único requisito es que la barra de direcciones del navegador permanezca sincronizada con la vista, simplemente puede usar el <h:button
lugar de <h:commandButton
. Esto funciona porque el <h:button
usa Javascript para generar una solicitud HTTP GET para iniciar y navegar hasta el flujo. La ID del flujo debe especificarse como el valor del atributo de outcome
:
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>
Ver también:
- Diferencia entre h: button y h: commandButton
Si el requisito es que se tengan que realizar algunas comprobaciones antes de otorgar el permiso para iniciar el flujo, debe inicializar manualmente y navegar al flujo de la siguiente manera:
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);
}
Tenga en cuenta que el parámetro no puede agregarse al botón en este caso, sino que debe agregarse al ámbito de flujo. También tenga en cuenta que la redirección al flujo debe hacerse mediante NavigationHandler#handleNavigation()
lugar de ExternalContext#redirect()
porque el alcance del flujo finaliza de lo contrario.
Ver también:
- ¿Se puede iniciar un flujo de rostros desde un Servlet?
- Obtenga programáticamente navegación desde faces-config.xml por resultado
- Omnifaces Faces.redirect pierde alcance de conversación