Performance Zone is brought to you in partnership with:

I started my software adventure with GWBasic programming language. I met with Visual Basic language after QuicBasic and I developed many applications with it until 2000. I stepped into the world of web with PHP. After that, my path crossed with Java! I have been developing enterprise applications with Java EE Technologies since 2005. JavaServer Faces and Spring frameworks are in my area of expertise. I’m trying to specialize in NoSQL Technologies. Hüseyin has posted 13 posts at DZone. You can read more from them at their website. View Full User Profile

JSF 2.2: Use Faces Flow

09.14.2013
| 6851 views |
  • submit to reddit
We will consider the uses of Faces Flow in this tutorial. For basic information about Faces Flow, you can take a look at this article.

I used the following tools and technologies in the sample application that I have developed for this tutorial:

  • JSF version 2.2
  • GlassFish version 4.0
  • JDK version 1.7
  • Maven version 3.0.5

The sample application has customer and order flows. The customer flow records the customer's name, surname and address. The order flow records the product, price and invoice address of the order.

1. Project directory structure

Screen Shot 2013-06-30 at 8.45.34 PM

2. Project dependencies

<dependency>
   <groupId>javax</groupId>
   <artifactId>javaee-api</artifactId>
   <version>7.0-b72</version>
    <scope>provided</scope>
</dependency>
            
<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.faces</artifactId>
   <version>2.2.0</version>
   <scope>provided</scope>
</dependency>

3. Customer.java 
public class Customer implements Serializable {
    
    @Produces
    @FlowDefinition
    public Flow defineFlow(@FlowBuilderParameter FlowBuilder flowBuilder) {
        String flowId = "customer";
        flowBuilder.id("", flowId);
        flowBuilder.viewNode(flowId, "/" + flowId + "/" + flowId + ".xhtml").markAsStartNode();
        
        flowBuilder.returnNode("returnFromCustomerFlow")
                   .fromOutcome("#{customerBean.returnValue}");
        
        return flowBuilder.getFlow();
    }
}

Customer class is a Java class that configures a flow with the same name. The only method this class has returns the javax.faces.flow.Flow class. What needs to be done primarily in the method is to define flow identity. Then, start the node and the return node is defined for flow.

4. order-flow.xml

<flow-definition id="order">
        
        <flow-return id="returnFromOrderFlow">
            <from-outcome>
                 #{orderBean.returnValue}
            </from-outcome>
        </flow-return>
                    
    </flow-definition>
The preceding flow configuration file is a Faces configuration file that includes a flow-definition element. If the XML configuration file is used in order to configure a flow, this file must be titled flowName-flow.xml. Please pay attention to this file, which configures a flow named "order" and is located within the flow directory of the same name.

First of all, in the configuration file, flow identity must be defined by using the ID attribute of the flow-definition element. Under this element, there must be a flow-return element that also defines the return point for the flow.

5. CustomerBean.java - OrderBean.java

@Named
@FlowScoped("customer")
public class CustomerBean implements Serializable {

    public CustomerBean() {
        System.out.println("CustomerBean has been created...");
    }
    
    
    public String getName() {
        return this.getClass().getSimpleName();
    }

    public String getReturnValue() {
        return "/index";
    }    
}

@Named
@FlowScoped("order")
public class OrderBean implements Serializable {

    public OrderBean() {
        System.out.println("OrderBean has been created...");
    }
    
    public String getName() {
        return this.getClass().getSimpleName();
    }

    public String getReturnValue() {
        return "/index";
    }  
}

FlowScoped is a CDI scope. A class that has @FlowScoped annotation is taken into account within the flow scope that is specified in the run time. A bean is activated when you enter the flow and deactivated when you exit the flow. The method named getReturnValue, which both beans have, returns the value of the returned node. 

6. index.xhtml 
<h1>Welcome to kodcu.com Faces Flow tutorial</h1>
        <h:form prependId="false">
            <h:panelGrid>
                
                <p>Click Customer to register your customer information and enter the customer flow.</p>
                <h:commandButton value="Customer" action="customer"/>
                
                <p>Click Order to register your order information and enter the order flow.</p>
                <h:commandButton value="Order" action="order"/>
                
            </h:panelGrid>
        </h:form>

Please note that the flows named "customer" and "order" are called by "customer" and "order" arguments in which commandButton components are passed to action attributes. These two arguments specify the call action of relevant flows.

7. order.xhtml

<h:form prependId="false">
            <h:panelGrid columns="3" cellpadding="2" cellspacing="2">
                
                <h:outputLabel for="product" value="Product: "/>
                <h:inputText  id="product" value="#{flowScope.product}" required="true" maxlength="20"/>
                <h:message for="product"/>
                
                <h:outputLabel for="price" value="Price: "/>
                <h:inputText id="price" value="#{flowScope.price}" required="true">
                    <f:convertNumber pattern="#,##0.00"/>
                </h:inputText>
                <h:message for="price"/>
                
                <h:outputLabel/>
                <h:panelGroup>
                    <h:commandButton value="next" action="orderA" />
                    <h:commandButton immediate="true" action="returnFromOrderFlow" value="Exit Flow"/>
                </h:panelGroup>
                
            </h:panelGrid>
        </h:form>

The new EL object #{flowScope} obtains the current flow data and maps the flow data for facesContext.getApplication().getFlowHandler().getCurrentFlowScope(). The object is also introduced as a local storage for flows.

8. Demo application

In the next article, we will consider flow calls and how flows pass parameters to each other. 


Published at DZone with permission of its author, Hüseyin Akdoğan. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)