Passing variables in JSF Flash Scope

This tutorial we’ll talk about JSF Flash Scope which is introduced in JSF 2.0 and is utilised when you need to pass parameters between views without the need to store them in the session. Variables stored in the flash scope will be available over a redirection and will be eliminated afterwards. It mostely is used with the POST-redirect-GET pattern.

Managing Values in JSF Flash Scope

Variables stored in the JSF flash scope survive only one redirect and then are deleted. We can read and write values into the JSF Flash Scope. The method setKeepMessages() stores the messages in the JSF flash scope so they can survive the POST-redirect-GET pattern, so they are available in the next page.

package com.memorynotfound;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.ComponentSystemEvent;

@ManagedBean
@RequestScoped
public class UserBean {

    private String firstName;
    private String lastName;

    public String goToConfirmView() {
        Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
        flash.put("firstName", firstName);
        flash.put("lastName", lastName);
        return "confirm?faces-redirect=true";
    }

    public String goToInputFormView() {
        return "input?faces-redirect=true";
    }

    public String insertValue() {
        Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();

        flash.setKeepMessages(true);
        pullValuesFromFlash(null);

        System.out.println("First name: " + firstName);
        System.out.println("Last name: " + lastName);

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Value inserted"));
        return "done?faces-redirect=true";
    }

    public void pullValuesFromFlash(ComponentSystemEvent e) {
        Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
        firstName = (String)flash.get("firstName");
        lastName = (String)flash.get("lastName");
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Input values into Flash Scope

If the users decides to go back to the input screen we pull the values from the flash scope with the preRenderView event.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <f:metadata>
        <f:event type="preRenderView" listener="#{userBean.pullValuesFromFlash}"/>
    </f:metadata>
    <style>
        .error {
            color: red;
        }
    </style>
</h:head>
<h:body>

    <h1>JSF Flash Scope Example</h1>

    <h:form>
        <h:messages styleClass="error"/>

        <h:panelGrid columns="2">
            <h:outputText value="First name:" />
            <h:inputText value="#{userBean.firstName}" required="true"/>

            <h:outputText value="Last name:" />
            <h:inputText value="#{userBean.lastName}" required="true" />
        </h:panelGrid>

        <h:commandButton value="Next" action="#{userBean.goToConfirmView}" />
    </h:form>

</h:body>
</html>

Keep values in the Flash Scope

This page displays the entered values from the input page. The #{flash.keep.firstName} obtains the values from the flash scope. #{flash.firstName} would also have worked. And tells JSF to keep the variables in the flash scope for the next request. This is needed because values in the flash scope only survive on redirect and we already had a redirect when entering the values.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:body>

    <h1>JSF Flash Scope Example</h1>

    <h:form>

        <h:panelGrid columns="2">
            <h:outputText value="First name:" />
            <h:outputText value="#{flash.keep.firstName}" />

            <h:outputText value="Last name:" />
            <h:outputText value="#{flash.keep.lastName}" />
        </h:panelGrid>

        <h:commandButton value="Edit" action="#{userBean.goToInputFormView}" />
        <h:commandButton value="Confirm" action="#{userBean.insertValue}" />

    </h:form>

</h:body>
</html>

Flash Values survive POST-redirect-GET pattern

We obtain the values from the flash scope in the preRenderView event to add the values to the managed bean. Note: that we are not keeping the values in the flash scope after the user clicks on back to input link.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
    <f:metadata>
        <f:event type="preRenderView" listener="#{userBean.pullValuesFromFlash}"/>
    </f:metadata>
</h:head>
<h:body>

    <h1>JSF Flash Scope Example</h1>

    <h:messages />

    <h:panelGrid columns="2">
        <h:outputText value="First name:" />
        <h:outputText value="#{userBean.firstName}" />

        <h:outputText value="Last name:" />
        <h:outputText value="#{userBean.lastName}" />
    </h:panelGrid>

    <h:link outcome="input" value="Back to input"/>

</h:body>
</html>

Demo

First time we enter values in the flash scope.

jsf flash scope

Values are put in the flash scope.

jsf flash scope example

Values stil survive in the flash scope.

jsf flash scope example

Values are automatically cleared in the flash scope because of the redirect.

jsf flash scope example

References

Download

Download it – jsf-flash-scope-example

You may also like...