Thursday, September 12, 2013

Spring Webflow Code example - Part II

For Part-I click on: Spring Webflow Code example - Part I

In order to invoke the webflow, let's create a link 'Create Order' in index.jsp. The link would refer to the path of the webflow xml.

index.jsp

<a href="http://www.blogger.com/webflowsample/pizza-order-flow.htm">Create Order</a>


Let's try to create the first Page "Customer details". Before landing on this page, we need to instantiate the model objects in controller. We will be adding new method to the controller for this.

Validation:

In the customer details page, let us try to validate 'First Name' for  mandatory field. Let us create a method to validate the customer in the controller. The method should follow a naming convention 'validateXXX' where XXX refers to the field name.

Changes to controller:

@Controller
public class PizzaOrderController {
        public Order createOrder(){
                Order order = new Order();
                Customer cust = new Customer();
                order.setCust(cust);
                return order;
        }
        public Event validateCust(Order order, MessageContext messageContext){
   
                          if(order.getCust().getFirstName() == null || order.getCust().getFirstName().trim() == ""){
                               MessageBuilder errorMessageBuilder = new MessageBuilder().error();
                               errorMessageBuilder.source("cust.firstName");
                               errorMessageBuilder.code("firstName.req");
                               messageContext.addMessage(errorMessageBuilder.build());
                               return new EventFactorySupport().error(this);
                 }
                 return new EventFactorySupport().success(this);
        }
}

Changes to Web Flow xml:

We need to invoke the 'createOrder' method before the first view of the webflow is displayed. So let's put this in 'on-start' as below.
Note that the result of the expression (which is the 'Order' object returned by the method) is put in flowScope. Webflow supports 5 scopes (conversation,flow,view,request,flash).
These scopes are internally managed by webflow and we can put objects in this scope by using a user defined key. A flowscope is valid till the end of the flow.

Let's add a view-state which is the view definition for our first page. The Id name should match the name of the view which we are going to show. (i.e, 'customerDetails').

Now, there are two possible transitions from this page: one is to second page (on click of next) and second is cancelling the order. So, we will add two transitions accordingly.

We have not yet invoked the validation logic. This should be validated upon click of 'next' button. So, lets invoke that as an expression within the transition to 'next' state.

<flow xmlns="http://www.springframework.org/schema/webflow"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
                          
        <on-start>
             <evaluate expression="pizzaOrderController.createOrder()" result="flowScope.order"/>
       </on-start>
        
        <view-state id="customerDetails" model="order">
             <transition on="next" to="selectPizza">
                 <evaluate expression="pizzaOrderController.validateCust(flowScope.order, messageContext)"/>
            </transition>     
            <transition on="cancel" to="cancelOrder" />
        </view-state>
                          
</flow>

JSP:

Let's create a jsp 'customerDetails.jsp'. Note that the action url should be '${flowExecutionUrl}' which is an implicit object provided by webflow. This will append the flow Id along with the URL. 

Now, this page needs two buttons, 'next' and 'cancel'. Clicking on next will take us to second page, whereas 'cancel' will cancel the ordering process. The button names should follow a certain naming convention for webflow to identify and process them. The names should be preceeded with '_eventId_'. So next button will have a name '_eventId_next'.

I'm not including the html formatting in the code segment to maintain clarity on what we are trying to accomplish.


<form:form modelAttribute="order" action="${flowExecutionUrl}">

<table width="30%"  border="0" cellspacing="3" cellpadding="1">
<tr>
    <td><spring:message code="firstName"/></td>
    <td><form:input path="cust.firstName"/></td>
    <td><form:errors path="cust.firstName" cssClass="error"/></td>
</tr>
<tr>
    <td><spring:message code="lastName"/></td>
    <td><form:input path="cust.lastName"/></td>
    <td><form:errors path="cust.lastName" cssClass="error"/></td>
</tr>
<tr>
    <td><spring:message code="email"/></td>
    <td><form:input path="cust.emailAddress"/></td>
    <td><form:errors path="cust.emailAddress" cssClass="error"/></td>
</tr>
</table>
<table width="20%"  border="0" cellspacing="3" cellpadding="1">
<tr><td>
    <button type="submit" id="next" name="_eventId_next">
        <spring:message code="next"/>
    </button>
</td>
<td>
    <button type="submit" id="cancel" name="_eventId_cancel">
        <spring:message code="cancel"/>
    </button>
</td></tr>
</table>

</form:form>




Cancel page:

Create a jsp 'cancelOrder.jsp' with a message for cancellation.
In the messages.properties file put a key value pair orderCancelMsg=Your order has been cancelled!

<spring:message code="orderCancelMsg"/>


                                                                                               ....Click here to continue

2 comments:

  1. i m getting page not found 404 when i click on create order link provided in index.jsp any1 can help me out on this ?

    ReplyDelete
  2. You can download the source code and work with it:
    https://docs.google.com/file/d/0B79rs4rdp74TSFdUeEZiaWpMMEU/edit?usp=sharing

    ReplyDelete