2012-06-25 22 views
27

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 siguiente ciclo de vida de solicitud de rostros y luego se borrará.Comprender el alcance de flash en JSF2

Supongamos que tengo dos páginas:

page01.xhtml:

<h:form> 
    <h:commandButton action="#{page01Bean.action}" /> 
</h:form> 

Page01Bean:

@ManagedBean 
@RequestScoped 
public class Page01Bean { 

     public void action(){ 
      FacesContext.getCurrentInstance().getExternalContext().getFlash().put("fooKey", "fooValue"); 
     } 

} 

page02.xhtml:

<h:outputText value="#{flash.fooKey}"/> 

Así que cuando se hace clic en el botón en page01.xhtml, unas caras solicitan ciclo de vida (decir el ciclo de vida A) se inicia y establece el valor en el flash en la clave llamado fooKey

Entonces abro otra pestaña del navegador y busque 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, ciclo de vida A) y mostrar fooValue en page02.xhtml. Sin embargo, no muestra nada.

Corrígeme lo que no entiendo del alcance del flash en este modelo. Muchas gracias

Respuesta

30

En resumen, las variables almacenadas en el alcance del flash sobrevivirán a una redirección y luego se descartarán. 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 por expresiones EL como

<h:outputLabel value="#{flash['param1']}" /> 

que muestra la "Hello World!" 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í.

23

La respuesta anterior es correcta, pero para completar, me gustaría decir que ha habido un lot of issues en las implementaciones de Mojarra con todo esto, pero finalmente lograron hacerlo funcionar correctamente en las versiones Mojarra 2.1.27 y 2.2.5 .

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 />.He aplicado una prueba básica siguiente SSCCE que muestra una gama más amplia de opciones, utilizando dos puntos de vista:

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:

+1

+1 por mencionar la aplicación con errores, se confunden fuera de mí. – mabi

+0

Establecerlo en EL no me sirvió de nada, pero en su lugar, puedo sugerir colocarlo en un bean administrado: 'FacesContext.getCurrentInstance(). GetExternalContext(). GetFlash(). Keep (" oValue "); \t \t this.oValue = (valueClass) FacesContext.getCurrentInstance() getExternalContext() GetFlash get() ("oValue");... ' Funciona para' GET'ting la página de nuevo, pero se rompe de alguna manera después de una solicitud de ajax + 'GET'. – DanielK