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: Flow Calls

09.14.2013
| 4107 views |
  • submit to reddit
In this tutorial, we will consider Faces Flow calls. For a basic level of information about Faces Flow, please check out this article and, for information about the usage of flows, you can check out JSF 2.2: Use Faces Flow tutorial.

Here, we will expand the sample application from the previous tutorial in a way that will allow the customer and order flows to call each other. This way, when an order flow is called from a customer flow, the recorded customer’s name, surname and address information is passed as a parameter to the order flow. When a customer flow is called from an order flow, the order's product, price and billing address information is passed as a parameter to the customer flow. 

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}");
       
        flowBuilder.inboundParameter("productOrder", "#{flowScope.productOrder}");
        flowBuilder.inboundParameter("priceOrder", "#{flowScope.priceOrder}");
        flowBuilder.inboundParameter("adressLine1Order", "#{flowScope.adressLine1Order}");
        flowBuilder.inboundParameter("adressLine2Order", "#{flowScope.adressLine2Order}");
        flowBuilder.inboundParameter("cityOrder", "#{flowScope.cityOrder}");
        flowBuilder.inboundParameter("stateOrder", "#{flowScope.stateOrder}");
        flowBuilder.inboundParameter("postalCodeOrder", "#{flowScope.postalCodeOrder}");
        flowBuilder.inboundParameter("countryOrder", "#{flowScope.countryOrder}");
        
        flowBuilder.flowCallNode("callOrder").flowReference("", "order")
                   .outboundParameter("firstNameCustomer", "#{customerBean.firstName}")
                   .outboundParameter("lastNameCustomer", "#{customerBean.lastName}")
                   .outboundParameter("adressLine1Customer", "#{customerBean.adressLine1}")
                   .outboundParameter("adressLine2Customer", "#{customerBean.adressLine2}")
                   .outboundParameter("cityCustomer", "#{customerBean.city}")
                   .outboundParameter("stateCustomer", "#{customerBean.state}")
                   .outboundParameter("postalCodeCustomer", "#{customerBean.postalCode}")
                   .outboundParameter("countryCustomer", "#{customerBean.country}");
        
        return flowBuilder.getFlow();
    }
}

The InboundParameter method adjusts the names and values of incoming parameters from the order flows.

The FlowCallNode method defines how a customer flow calls an order flow. The “callOrder” argument that was passed to the method defines the action of calling the flow. The chained flowReference method defines the actual name of the flow to call.

When the order flow is called, the outboundParameter method is called in order to define the parameters to be passed. 

For an explanation of the remaining code, you can check out the previous tutorial

4. order-flow.xml

<flow-definition id="order">
        
        <flow-return id="returnFromOrderFlow">
            <from-outcome>#{orderBean.returnValue}</from-outcome>
        </flow-return>
                    
        <inbound-parameter>
            <name>firstNameCustomer</name>
            <value>#{flowScope.firstNameCustomer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>lastNameCustomer</name>
            <value>#{flowScope.lastNameCustomer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>adressLine1Customer</name>
            <value>#{flowScope.adressLine1Customer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>adressLine2Customer</name>
            <value>#{flowScope.adressLine2Customer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>cityCustomer</name>
            <value>#{flowScope.cityCustomer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>stateCustomer</name>
            <value>#{flowScope.stateCustomer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>postalCodeCustomer</name>
            <value>#{flowScope.postalCodeCustomer}</value>
        </inbound-parameter>
        <inbound-parameter>
            <name>countryCustomer</name>
            <value>#{flowScope.countryCustomer}</value>
        </inbound-parameter>
        
        <flow-call id="callCustomer">
            <flow-reference>
                <flow-id>customer</flow-id>
            </flow-reference>
            <outbound-parameter>
                <name>productOrder</name>
                <value>#{orderBean.product}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>priceOrder</name>
                <value>#{orderBean.price}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>adressLine1Order</name>
                <value>#{orderBean.adressLine1}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>adressLine2Order</name>
                <value>#{orderBean.adressLine2}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>cityOrder</name>
                <value>#{orderBean.city}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>stateOrder</name>
                <value>#{orderBean.state}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>postalCodeOrder</name>
                <value>#{orderBean.postalCode}</value>
            </outbound-parameter>
            <outbound-parameter>
                <name>countryOrder</name>
                <value>#{orderBean.country}</value>
            </outbound-parameter>
        </flow-call> 
 </flow-definition>  
           

In this code, the XML configuration is similar to the programmatic configuration. Incoming parameters for the order flow are defined with the inbound-parameter element. 

Flow-call elements define how an order flow will call a customer flow. The "callCustomer" argument that is passed to the ID attribute of the element defines the action of calling the flow

Flow-reference elements within the element defines the actual name of the flow for the call. When a customer flow is called, parameters to be passed are defined by the outboundParameter element. 

For an explanation of the remaining parts of the XML configuration, you can check out the previous tutorial. 

5. CustomerBean.java – OrderBean.java

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

    private String firstName;
    private String lastName;
    private String adressLine1;
    private String adressLine2;
    private String city;
    private String state;
    private String postalCode;
    private String country;
    
    
    public CustomerBean() {
        System.out.println("CustomerBean has been created...");
    }
    
    public String getName() {
        return this.getClass().getSimpleName();
    }

    public String getReturnValue() {
        return "/index";
    }
 
 /* getter and setter methods */
}

6. Demo application





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.)