Understand Flash Scope in JSF2
Solution 1:
In short, variables stored in the flash scope will survive a redirection and they will be discarded afterwards. This is really useful when implementing a Post-Redirect-Get pattern.
If you try to navigate to another page by redirect and access the attributes on load, they will be there. After that request is done the values in the flash will be discarded. For example:
You're in page1.xhtml and you have a commandLink that redirects to a new page with a method like this one (Note: I'll use implicit navigation).
public String navigateToPageB() {
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("param1", "Hello World!");
return "pageB?faces-redirect=true";
}
When pageB.xhtml is rendered, you can access those values by EL expressions such as
<h:outputLabel value="#{flash['param1']}" />
which will display the "Hello World!" string we saved earlier in navigateToPageB.
As for your question, by opening a new tab in your explorer you're not accessing the same context you were accessing on your previous tab, so your variable will not be available there.
Solution 2:
Previous answer is correct, but just for completeness I would like to say there have been a lot of issues in Mojarra implementations with all this stuff, but finally they achieved to make it work properly in Mojarra 2.1.27 and 2.2.5 versions.
As @Gamb says, the aim of the flash scope is to keep a parameter alive mapping it internally across redirection. We can also keep the parameter alive for longer if we need it. Apart from the mentioned way , FacesContext#getCurrentInstance#getExternalContext#getFlash#put
, there's also the chance to set the parameter via EL expression, using <c:set />
. I've implemented a basic test following SSCCE which shows a broader range of options, using two views:
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>
See also:
- JSF flash documentation
- Keeping the flash parameters when user manually reloads the view