jsf etiquetas
Comprender el alcance de Flash en JSF2 (2)
Por lo que entiendo, los objetos colocados dentro del alcance de Flash en un ciclo de vida de solicitud de rostros estarán disponibles para el próximo ciclo de vida de solicitud de caras y luego se borrarán.
Supongamos que tengo dos páginas:
page01.xhtml :
<h:form>
<h:commandButton action="#{page01Bean.action}" />
</h:form>
Página01Bean:
@ManagedBean
@RequestScoped
public class Page01Bean {
public void action(){
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("fooKey", "fooValue");
}
}
page02.xhtml :
<h:outputText value="#{flash.fooKey}"/>
Entonces, cuando se hace clic en el botón de la page01.xhtml
se page01.xhtml
un ciclo de vida de solicitud de rostros (por ejemplo, ciclo de vida A) y se establece el valor en el flash debajo de la tecla llamada fooKey
Luego abro otra pestaña del navegador y page02.xhtml
. Otro ciclo de vida de solicitud de rostros (por ejemplo, ciclo de vida B) comienza a mostrar esta página. Esperaba que el ciclo de vida B pudiera acceder al alcance del flash de su ciclo de vida anterior (es decir, el ciclo de vida A) y mostrar fooValue
en la page02.xhtml
. Sin embargo, no muestra nada.
Por favor, corrígeme lo que no entiendo del alcance del flash en este modelo. Muchas gracias
En resumen, las variables almacenadas en el alcance del flash sobrevivirán a una redirección y luego serán descartadas. Esto es realmente útil cuando se implementa un patrón Post-Redirect-Get.
Si intenta navegar a otra página redirigiendo y acceder a los atributos en carga, estarán allí. Después de que se realiza la solicitud, los valores en el flash se descartarán. Por ejemplo:
Estás en page1.xhtml y tienes un commandLink que redirige a una nueva página con un método como este (Nota: usaré navegación implícita).
public String navigateToPageB() {
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("param1", "Hello World!");
return "pageB?faces-redirect=true";
}
Cuando se representa pageB.xhtml, puede acceder a esos valores mediante expresiones EL tales como
<h:outputLabel value="#{flash[''param1'']}" />
que mostrará el "¡Hola mundo!" cadena que guardamos anteriormente en navigateToPageB.
En cuanto a su pregunta, al abrir una nueva pestaña en su explorador no está accediendo al mismo contexto al que estaba accediendo en su pestaña anterior, por lo que su variable no estará disponible allí.
La respuesta anterior es correcta, pero para completar, me gustaría decir que ha habido muchos problemas en las implementaciones de Mojarra con todo esto, pero finalmente lograron hacerlo funcionar correctamente en las versiones 2.1.27 y 2.2.5 de Mojarra.
Como dice @Gamb, el objetivo del alcance del flash es mantener vivo un parámetro mapeándolo internamente a través de la redirección. También podemos mantener el parámetro activo por más tiempo si lo necesitamos. Además de la forma mencionada, FacesContext#getCurrentInstance#getExternalContext#getFlash#put
, también existe la posibilidad de establecer el parámetro mediante expresión EL, usando <c:set />
. Implementé una prueba básica después de SSCCE que muestra una gama más amplia de opciones, usando dos vistas:
Bean1
@ManagedBean
@ViewScoped
public class Bean1 implements Serializable {
/**
* Just takes the given param, sets it into flash context and redirects to
* page2
*
* @param inputValue
* @return
*/
public String goPage2(String inputValue) {
FacesContext.getCurrentInstance().getExternalContext().getFlash()
.put("param", inputValue);
return "page2?faces-redirect=true";
}
}
page1.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head />
<h:body>
<!-- Sets the first flash param at the action method, which redirects to page 2 -->
<h:form>
<h:inputText value="#{inputValue}" />
<h:commandButton action="#{bean1.goPage2(inputValue)}"
value="Go Page 2" />
</h:form>
<!-- Sets the second flash param -->
<c:set target="#{flash}" property="param2" value="Myparam2" />
<!-- Tries to retrieve both of the params.
Note none of them is displayed at the first page hit.
If page refreshed, the second param which has been already set
using c:set above, will be displayed -->
<p>Param1: #{flash[''param'']}</p>
<p>Param2: #{flash[''param2'']}</p>
</h:body>
</html>
Bean2
@ManagedBean
@ViewScoped
public class Bean2 implements Serializable {
public String getParam() {
/**
* Takes the parameter from the flash context
*/
return (String) FacesContext.getCurrentInstance().getExternalContext()
.getFlash().get("param");
}
}
page2.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head />
<!-- This page just displays the received params -->
<h:body>
<!-- Different ways to retrieve the params from the flash scope -->
<p>Param1: #{bean2.param}</p>
<p>Param1: #{flash.param}</p>
<p>Param1: #{flash[''param'']}</p>
<p>Param2: #{flash[''param2'']}</p>
<!-- Keep the first param for next redirection -->
#{flash.keep.param}
<!-- Return to page1 and see how the first param is retained -->
<h:button outcome="page1?faces-redirect=true" value="return to 1" />
</h:body>
</html>
Ver también:
- Documentación flash JSF
- Mantener los parámetros de flash cuando el usuario recarga manualmente la vista