With JSF 2.2, the JavaServer Faces technology allows you to create a set of pages with the new scope FlowScoped, that scope is greater than request scope and less than session scope. The FlowScoped scope depends on the concept of procedure where is declared a well defined entry point and a return value. The entry point should be used for starting the flow whereas the return is used for finishing the flow. In between the managed beans are defined for that scope, so once the flow has entered by its entry point the all managed beans that are defined as FlowScoped for that flow have created and once the flow has finished the FlowScoped managed beans are destroyed.
In other words, the flow has a scope, allowing information to be available only during the invocation of the flow. Such information is not available outside the scope of the flow and doesn’t consume any resources once the flow returns.
You can configure the flow using three types of configuration:
- Using the faces-config.xml as introduced in this tutorial.
- Using the file named as same name of the flow but it ends with .xml.
- Using created class and annotated using @FlowDefinition.
The using of FlowScoped isn’t possible without using of CDI (Context Dependency Injection), so in order to define a FlowScoped managed beans, you have to include any of the CDI implementation. For that purpose we’ve used a JBoss Weld Implementation.
Also Read:
1. Managed Bean
RegisterBean.java
package net.javabeat.jsf; import java.util.ArrayList; import java.util.List; import javax.faces.flow.FlowScoped; import javax.inject.Named; import net.javabeat.jsf.data.Student; @Named(value="register") @FlowScoped(value="register") public class RegisterBean { private int index = 0; private String name; private String age; private String address; private String major; private String graduateYear; private List<Student> students = new ArrayList<Student>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public String getGraduateYear() { return graduateYear; } public void setGraduateYear(String graduateYear) { this.graduateYear = graduateYear; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } public String fillBasicInfo (){ index++; return "registera"; } public String fillAcademicInfo(){ index++; return "registerb"; } public String backIntoBasicInfo(){ index--; return "registera"; } public String save(){ Student student = new Student(); student.setName(this.name); student.setAddress(this.address); student.setAge(this.age); student.setMajor(this.major); student.setGraduateYear(this.graduateYear); this.students.add(student); this.name = ""; this.major = ""; this.graduateYear = ""; this.address = ""; this.age = ""; this.index = 0; return ""; } }
Student.java
package net.javabeat.jsf.data; public class Student { private String name; private String age; private String address; private String major; private String graduateYear; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public String getGraduateYear() { return graduateYear; } public void setGraduateYear(String graduateYear) { this.graduateYear = graduateYear; } }
2. Faces Configuration File
faces-config.xhtml
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> <application> <resource-bundle> <base-name>net.javabeat.jsf.application</base-name> <var>msg</var> </resource-bundle> </application> <flow-definition id="register"> <flow-return id="endFlow"> <from-outcome>/index</from-outcome> </flow-return> </flow-definition> </faces-config>
- Based on the faces-config.xml you’ve a Flow named register
- Based on the name of the flow, the entry page must be named as the name of the flow (Start Node)
- The consequences pages of the flow can have any name
- The return page must be located outside of the flow directory (See index.xhtml). The return is used in order to end the flow, the provided flow-return determines the token that cause the flow to be ended and the view to be displayed.
- The flow doesn’t call any another flow
- The flow doesn’t pass parameters to another flow
3. The Views
index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <f:view> <h:form> <h1>JavaBeat JSF 2.2 Examples</h1> <h2>JSF2 FlowScoped Example</h2> <h:commandButton value="Start Flow" action="register"></h:commandButton> </h:form> </f:view> </html>
register.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <f:view> <h:form> <h1>JavaBeat JSF 2.2 Examples</h1> <h2>JSF2 FlowScoped Example</h2> <br/> <br/> <h:outputText value="Page # #{register.index}" style="font-size:15px;"/> <br/> <br/> <h:outputText value="JavaBeat Training Center"/> <br/> <br/> <h:outputText value="Start"/> #{' '} <h:commandButton value="Enter Registration Info" action="#{register.fillBasicInfo}"/> </h:form> </f:view> </html>
registera.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <f:view> <h:form> <h1>JavaBeat JSF 2.2 Examples</h1> <h2>JSF2 FlowScoped Example</h2> <br/> <h:outputText value="Page # #{register.index}" style="font-size:15px;"/> <br/> <h:outputText value="Basic Information:"/> <br/> <h:outputText value="Enter Name:"/>#{' '}<h:inputText value="#{register.name}"></h:inputText> <br/> <h:outputText value="Enter Address:"/>#{' '}<h:inputText value="#{register.address}"></h:inputText> <br/> <h:outputText value="Enter Age:"/>#{' '}<h:inputText value="#{register.age}"></h:inputText> <br/> <h:commandButton value="Enter Academic Info" action="registerb"></h:commandButton> </h:form> </f:view> </html>
registerb.xhtml
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <f:view> <h:form> <h1>JavaBeat JSF 2.2 Examples</h1> <h2>JSF2 FlowScoped Example</h2> <br/> <h:outputText value="Page # #{register.index}" style="font-size:15px;"/> <br/> <h:outputText value="Academic Information:"/> <br/> <h:outputText value="Enter Major:"/>#{' '}<h:inputText value="#{register.major}"></h:inputText> <br/> <h:outputText value="Enter Graduate Year:"/>#{' '}<h:inputText value="#{register.graduateYear}"></h:inputText> <br/> <h:commandButton value="Back" action="registera"></h:commandButton> <h:commandButton value="Save" action="#{register.save}"></h:commandButton> <h:commandButton value="New Student" action="register"></h:commandButton> <h:commandButton value="End Flow" action="/index"></h:commandButton> <br/> <h:dataTable value="#{register.students}" var="student" border="1"> <f:facet name="header"> <h:outputText value="Registerd Students"></h:outputText> </f:facet> <h:column> <f:facet name="header"> <h:outputText value="Name"/> </f:facet> <h:outputText value="#{student.name}"></h:outputText> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Major"/> </f:facet> <h:outputText value="#{student.major}"></h:outputText> </h:column> </h:dataTable> </h:form> </f:view> </html>
4. The Deployment Descriptor
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5" metadata-complete="true"> <context-param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2 </description> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>javax.faces.application.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.xml</param-value> </context-param> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <listener> <listener-class>org.jboss.weld.environment.servlet.Listener</listener-class> </listener> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <resource-env-ref> <resource-env-ref-name>BeanManager</resource-env-ref-name> <resource-env-ref-type> javax.enterprise.inject.spi.BeanManager </resource-env-ref-type> </resource-env-ref> </web-app>
5. Weld Dependency
<dependency> <groupId>org.jboss.weld.servlet</groupId> <artifactId>weld-servlet</artifactId> <version>1.1.18.Final</version> </dependency>
6. webapp/META-INF/context.xml
<Context> <Resource name="BeanManager" auth="Container" type="javax.enterprise.inject.spi.BeanManager" factory="org.jboss.weld.resources.ManagerObjectFactory"/> </Context>
7. webapp/WEB-INF/beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> </beans>
8. Directory Structure
9. JSF 2 FlowScoped Demo
- The below snapshots show you the using of FlowScoped for implementing a registration module. In that module the admin entry of a flow in order to register a student, but meanwhile the admin has a chance to cancel the flow or save the student being registered.
- Save the student means the admin still in the flow, and it can also register another one, but once the admin has cancelled the flow, the all registered students are removed together with their managed beans that are held them.
- The user has entered the flow by navigating into register.xhtml that represents the entry point for the defined register flow.
- All of those managed beans associated with the flow are created.
- The user has navigated into the first node of the flow.
- By entering the academic information, the user has navigated into second node.
- If the user has activated the Back, the previous node of the flow should be displayed.
- If the user has activated the Save, the student will be saved and the current node of the flow will remain.
- If the user has activated the End Flow, the flow will be ended and the beans associated will be destroyed. Index view has displayed.
- If the user has activated the New Student, the same flow is continued and it will be remaining for holding the data. Register view has displayed.
- Result of Save activation.
- The return view that should be displayed, once the Flow has returned (ended).
- By returning from the Flow, all of these associated managed beans are destroyed.
- If the user has been entering again into the flow, the associated managed beans are initialized again for serving the user request.