Spring Web Webflow


Published on

Spring MVC Webflow

Published in: Technology, Business
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Spring Web Webflow

  1. 1. Connecting the Views to Work Together
  2. 2. Spring Web Flow Spring Web Flow is an extension to Spring MVC thatprovides for the development of conversation-stylenavigation in a web application. The key features provided for by Spring Web Flow are: ■ The ability to define an application’s flow external to theapplication’s logic. ■ The ability to create reusable flows that can be usedacross multiple applications. Spring Web Flow loosens the coupling between anapplication code and its page flow by enabling to define theflow in a separate, selfcontained flow definition.
  3. 3. Installing Spring Web Flow Spring Web Flow, is a subproject of the Spring Framework,but isn’t part of the Spring Framework, hence is required toload Spring Web Flow JAR files in application classpath. Spring Web Flow can be added in the application usingMaven 2 by setting dependencies in the pom.xml file asfollows: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflow</artifactId> <version>1.0.3</version> <scope>compile</scope> </dependency>
  4. 4. Setting up FlowController FlowController is a Spring MVC controller that acts as a frontcontroller for Spring Web Flow applications. FlowController is responsible for handling all requestspertaining to a flow. FlowController is declared in a Spring application context asfollows: <bean id="flowController" class="org.springframework.webflow.executor.mvc. ➥ FlowController"> <property name="flowExecutor" ref="flowExecutor" /> </bean> The flowExecutor property is the only mandatory property wiredwith a flow executor, which ultimately carries out the stepsdescribed in a flow.
  5. 5. Setting up FlowController A mapping URL is used to interact with the Spring Web Flow. It is configured to the FlowController using handler mappings such asSimpleUrlHandlerMapping as follows: <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="flow.htm">flowController</prop> </props> </property> </bean> SimpleUrlHandlerMapping is most flexible handler mapping as it allows tomap virtually any URL pattern to any controller in the same application. ControllerClassNameHandlerMapping can be used if the application iscompletely flow-based or if the application’s other controllers are namedappropriately with respect to the URL patterns they’ll be mapped to. DispatcherServlet is also configured in the application’s web.xml file asFlowController is a Spring MVC controller.
  6. 6. Configuring Flow Executor The Flow Executor keeps track of all of the flows that are currently beingexecuted and directs each flow to the state they should go next. In Spring 2.0, the flow executor is configured using Spring Web Flow’scustom configuration schema, by adding Spring Web Flow schema to theSpring application context’s XML file as follows: <beans xmlns= http://www.springframework.org/schema/beans xmlns:flow= http://www.springframework.org/schema/webflow-config xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd"> ……… </beans> A flow executor is declared using the <flow:executor> element as follows: <flow:executor id="flowExecutor“ registry-ref="flowRegistry" />
  7. 7. Under the Hood: Flow Executor The <flow:executor> element is used to declare a FlowExecutorFactoryBean in the Springapplication context. <bean id="flowExecutor“ class="org.springframework.webflow.config. ➥ FlowExecutorFactoryBean"> <property name="definitionLocator“ ref="flowRegistry"/> <property name="executionAttributes"> <map> <entry key="alwaysRedirectOnPause"> <value type="java.lang.Boolean">true</value> </entry> </map> </property> <property name="repositoryType“ value="CONTINUATION"/> </bean> FlowExecutorFactoryBean uses a flow registry to keep track of all of the flow definitionthat it may need. The flow registry is given to the flow executor through <flow:executor>’s registry-refattribute or through FlowExecutorFactoryBean’s definitionLocator property.
  8. 8. Registering flow definitions The flow registry is effectively a librarian that curates a collectionof flow definitions. When the flow executor needs a flow, it will ask the flow registryfor it. A flow registry can be configured in Spring 2.0 using the<flow:registry> element, as follows: <flow:registry id="flowRegistry"> <flow:location path="/WEB-INF/flows/**/*-flow.xml" /> </flow:registry> The <flow:registry> element must contain one or more<flow:location> elements which identifies the path to one ormore flow definitions that the flow registry should manage. When a flow definition is loaded into the flow registry, it isregistered with a name that is equal to the filename of the flowdefinition after chopping off the file extension (such as “.xml”).
  9. 9. Under the hood: Flow Registry The <flow:registry> element is converted toXmlFlowRegistryFactoryBean <bean> element as follows: <bean id="flowRegistry“class="org.springframework.webflow.engine. ➥ builder.xml.XmlFlowRegistryFactoryBean"> <property name="flowLocations"> <list> <value>/WEB-INF/flows/**/*-flow.xml </value> </list> </property> </bean> The XmlFlowRegistryFactoryBean is the class that hides behindthe curtain of the <flow:registry> element. The flowLocations property of XmlFlowRegistryFactoryBeanitemizes the flow definitions to be loaded into the registry.
  10. 10. Spring Web Flow Basics: States In Spring Web Flow, three main elements make up anapplication flow: states, events, and transitions. States are points in a flow where some activity takesplace. Activities can be the application performing some logic,or it could be where the user is presented with a pageand asked to take some action. The selection of states provided by Spring Web Flowmakes it possible to construct virtually any arrangementof functionality into a conversational web application. View states and Action states represents the user’sside and the application’s side of conversationrespectively.
  11. 11. Spring Web Flow’s StatesState type XML element PurposeAction <action-state> Action states are where the logic of the flow takesplace. It mostly store, retrieve, derive, process info.Decision <decision-state> Decision states branch the flow in two or moredirections. Examine info to make routing decision.End <end-state> The end state is the last stop for a flow. Here theflow is terminated and user is sent to a final view.Start <start-state> The start state is the entry point for a flow. It servesas a reference point to bootstrap a flow.Subflow <subflow-state> A subflow state starts a new flow within the contextof a flow that is already underway.View <view-state> A view state pauses the flow and invites the user toparticipate in the flow. Used to communicate info.
  12. 12. Basics: Events and Transitions Once a state has completed, it fires an event. The event is simply a String value that indicates theoutcome of the state. The event fired by a state should be mapped to atransition to serve any purpose. Transitions defines the actual flow unlike the statewhich defines an activity within a flow. A transition indicates which state the flow should goto next.
  13. 13. Flow Variables Flows in Spring Web Flow are defined in XML with allflow definition files are rooted with the <flow>element. To define flow variables declare a simple domain beancarrying the necessary information, e.g. Order object. The domain object is made available to all of the statesin the flow by declaring it in the flow definition filewith a <var> element as follows: <var name="order“class="com.springinaction.pizza.domain.Order“scope="flow"/>
  14. 14. Flow Scopes Flow variables can be declared to live in one of fourdifferent scopes as below:Scope VisibilityRequest If an object is created in Request scope, it is only visible withinthe context of the current request. Request-scoped variables donot survive redirects.Flash An object created in Flash scope is visible within the context ofthe current request and until the next user event is triggered.Flash-scoped variables live beyond redirects.Flow If an object is created in Flow scope, it will be visible within thecontext of the current flow execution, but will not be visible tosubflows.Conversation Objects created in Conversation scope are visible within thecontext of the current flow execution as well as in the context ofsubflow executions.
  15. 15. Start and End states All flows begin with a start state. The only thing that occurs within a start state is that atransition is performed to the next state. All flows must have exactly one <start-state> to indicatewhere the flow should begin e.g. <start-state idref="askForPhoneNumber" /> The idref attribute indicates the beginning state of theflow, is the only attribute available to <start-state>. The end state is defined as follows: <end-state id="finish“ view="orderComplete" /> An end state terminates the flow and then displays a viewspecified by the view attribute. The logical view name in end state is mapped to an actualview implementation using a Spring MVC view resolver.
  16. 16. Start and End states The end state could start over with a brand new flowinstead of jumping out of the flow completely. <end-state id="finish" view="flowRedirect:PizzaOrder-flow" /> The flowRedirect: directive tells the Spring Web Flowto redirect the user to the beginning of a flow, e.g. startof the current flow just finished. A flow can have multiple <end-state>s unlike single<start-state>, in order to define alternate endings for aflow.
  17. 17. Example Flow1: Pizza Delivery
  18. 18. Web Flow1: Pizza Delivery <var name="order“ class="com.springinaction.pizza.domain.Order" scope="flow"/> <start-state idref="askForPhoneNumber" /> <view-state id="askForPhoneNumber“ view="phoneNumberForm"> <transition on="submit" to="lookupCustomer" /> </view-state> <decision-state id="checkDeliveryArea"> <if test="${flowScope.order.customer.inDeliveryArea}“ then="showOrder" else="warnNoDeliveryAvailable"/> </decision-state> <view-state id="warnNoDeliveryAvailable“ view="deliveryWarning"> <transition on="continue" to="showOrder" /> </view-state> <end-state id="finish“ view="flowRedirect:PizzaOrder-flow" />
  19. 19. Web Flow1: Pizza Delivery <view-state id="askForPhoneNumber“ view="phoneNumberForm"> <transition on="submit" to="lookupCustomer" /> </view-state> <action-state id="lookupCustomer"> <action bean="lookupCustomerAction" /> <transition on="success“ to="showOrder" /> <transition on-exception="com.springinaction.pizza.service. ➥ CustomerNotFoundException“ to="addNewCustomer" /> </action-state> <view-state id="addNewCustomer" view="newCustomerForm"> <render-actions> // to create a blank Customer object to bind form data <action bean="customerFormAction“ method="setupForm"/> </render-actions> <transition on="submit" to="showOrder"> <action bean="customerFormAction" method="bind" /> <evaluate-action expression= "flowScope.order.setCustomer(requestScope.customer)" /> </transition> </view-state>
  20. 20. Example View: phoneNumberForm <h2>Customer Lookup</h2> <form method="post" action="flow.htm"> <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"> <b>Phone number: </b> <input type="text" name="phoneNumber"/><br/> <input type="submit" class="button" name="_eventId_submit" value="Submit"/> </form>
  21. 21. FlowController All links within a Spring Web Flow application goesthrough FlowController’s URL mapping. The forms are also submitted to FlowController URL bysetting the action parameter to flow.htm which in turn ismapped to FlowController. The FlowController identifies the flow using the_flowExecutionKey parameter, set to the flow executionkey which is submitted along with the form data. The submit button named “_eventId_submit” triggers anevent to Spring Web Flow from a form submission. When the form is submitted, the name of the parameter issplit into two parts. The first part being _eventId, signals the event identified,while the second part being submit, is the name of theevent to be triggered when the form is submitted.
  22. 22. Web Flow Action Bean The bean referenced by the bean attribute of <action> must implementSpring Web Flow’s Action interface. The execute() is the only mandatory method of the Action interface. public class LookupCustomerAction implements Action { public Event execute(RequestContext context) throws Exception { String phoneNumber = context.getRequestParameters().get("phoneNumber"); Customer customer = customerService.lookupCustomer(phoneNumber); Order order = (Order) context.getFlowScope().get("order"); order.setCustomer(customer); return new Event(this, "success"); } private CustomerService customerService; // Bean injected }
  23. 23. Example View: newCustomerForm <%@ taglib prefix="form“uri="http://www.springframework.org/tags/form" %> <h2>New customer</h2> <form:form action="flow.htm“ commandName="order.customer"> <input type="hidden" name="_flowExecutionKey“ value="${flowExecutionKey}"/> <b>Phone: </b> ${requestParameters.phoneNumber} <br/> <b>Name: </b> <form:input path="name" /><br/> <b>Street address: </b> <form:input path="streetAddress" /><br/> <b>City: </b> <form:input path="city" /><br/> <b>State: </b> <form:input path="state" /><br/> <b>Zip: </b> <form:input path="zipCode" /><br/> <input type="submit" class="button“ name="_eventId_submit" value="Submit"/> <input type="submit" class="button" name="_eventId_cancel" value="Cancel"/> </form:form>
  24. 24. FlowAction When the user submits the form, the form data is binds toa back-end Data object. Spring Web Flow provides FlowAction, a special SpringWeb Flow Action implementation that deals with commonform-binding logic. The FlowAction is configured as follows: <bean id="customerFormAction" class="org.springframework.webflow.action.FormAction"> <property name="formObjectName" value="customer" /> <property name="formObjectScope" value="REQUEST" /> <property name="formObjectClass" value="com.springinaction.pizza.domain.Customer" /> </bean>
  25. 25. FlowAction FormAction has three important properties that describe theobject that will be bound to the form. The formObjectName property specifies the name of the object,formObjectScope specifies the scope, and formObjectClassspecifies the type. The setupForm() method of FormAction creates a blankCustomer object inorder to bind the form data to as follows: <render-actions> <action bean="customerFormAction“ method="setupForm"/> </render-actions> Render actions are a way of associating an action with therendering of a view. FormAction’s setupForm() is similar to the Spring MVC formcontroller’s formBackingObject() which prepares an object to bebound to a form.
  26. 26. Binding during Transition <transition on="submit" to="showOrder"> <action bean="customerFormAction" method="bind" /> <evaluate-action expression= "flowScope.order.setCustomer(requestScope.customer)" /> </transition> The form data is first bind to the form-backing Customer objectand set to the customer property of the flow-scoped Order. Thisis a two-step process: First, an <action> element is used to ask FormAction’s bind()method to bind the submitted form data to the form-backingCustomer object that is in request scope. Next, with a fully populated Customer object in request scope,an <evaluate-action> is used to copy the request-scopedCustomer object to the Order object’s customer property.
  27. 27. Example Flow2: Pizza Order
  28. 28. Web Flow2: Pizza Order <view-state id="showOrder" view="orderDetails"> <transition on="addPizza" to="addPizza" /> <transition on="continue" to="takePayment" /> </view-state> <view-state id="addPizza" view="newPizzaForm"> <render-actions> <action bean="pizzaFormAction" method="setupForm"/> </render-actions> <transition on="submit" to="showOrder"> <action bean="pizzaFormAction" method="bind" /> <evaluate-action expression= "flowScope.order.addPizza(requestScope.pizza)" /> </transition> </view-state>
  29. 29. Web Links in Web Flow <a href="flow.htm?_flowExecutionKey=${flowExecutionKey} ➥ &_eventId=addPizza">Add Pizza</a> There are three very important elements of the link’s href attribute thatguide Spring Web Flow: ■ All the links within a flow must go through the FlowController.Hence the root of the link is flow.htm, the URL pattern mapped to theFlowController. ■ To identify the flow execution to Spring Web Flow, we’ve set the_flowExecutionKey parameter to the page-scoped ${flowExecutionKey}variable. This way FlowController will be able to distinguish one user’sflow execution from another. ■ Finally, the _eventId parameter identifies the event to fire when thislink is clicked on. For example above, we’re firing the addPizza event,which, as defined in the showOrder state, should trigger a transition tothe addPizza state.
  30. 30. Web Flow3: Pizza Payment <view-state id="takePayment" view="paymentForm"> <transition on="submit" to="submitOrder"> <bean-action bean="paymentProcessor“ method="approveCreditCard"> <method-arguments> <argument expression= "${requestParameters.creditCardNumber}"/> <argument expression= "${requestParameters.expirationMonth}"/> <argument expression= "${requestParameters.expirationYear}"/> <argument expression= "${flowScope.order.total}" /> </method-arguments> </bean-action> </transition> <transition on-exception= "com.springinaction.pizza.PaymentException“ to="takePayment" /> </view-state> <action-state id="submitOrder"> <bean-action bean="orderService" method="saveOrder"> <method-arguments> <argument expression="${flowScope.order}" /> </method-arguments> </bean-action> <transition on="success" to="finish" /> </action-state>
  31. 31. Action versus Bean-Action The downside of using <action> is that the action classmust be an implementation of Spring Web Flow’sAction interface, without allowing pure POJO actionimplementations. The <bean-action> provides a nonintrusive alternative,enabling to invoke any method on any class configuredin the Spring application context, withoutimplementing a Spring Web Flow–specific interface.
  32. 32. Global Transitions The links that fire cancel events within the flow arehandled by allowing the flow to transition to the finishstate in-order to close down the flow execution. Spring Web Flow offers the ability to define globaltransitions to avoid multiple definitions of redundant(cancel) transitions occurring throughout the flow. Global transitions are transition definitions that areapplicable from any flow state. Global transitions can be added to a flow by using <global-transitions> element as a child of the <flow> element andplace <transition> elements within it as follows: <global-transitions> <transition on="cancel" to="finish" /> </global-transitions>
  33. 33. Decision States A decision state is the Spring Web Flow equivalent of an if/elsestatement in Java. It evaluates some Boolean expression and based on the resultswill send the flow in one of two directions. Decision states are defined with the <decision-state> element asfollows: <decision-state id="checkDeliveryArea"> <if test="${flowScope.order.customer.inDeliveryArea}" then="showOrder" else="warnNoDeliveryAvailable"/> </decision-state> The test attribute specifies some expression to be evaluated. If the expression evaluates to true, the flow will transition to thestate specified by the then attribute. Otherwise, the flow willtransition to the state given in the else attribute.
  34. 34. Subflows and Substates As the flow definitions become lengthy, it is advantageous to extract arelated set of states into their own flow and to reference that flow fromthe main flow. E.g. CustomerInfo-flow as below: <var name="customer“ class="com.springinaction.pizza.domain.Customer" scope="flow"/> <start-state idref="askForPhoneNumber" /> <decision-state id="checkDeliveryArea"> <if test="${flowScope.customer.inDeliveryArea}“ then="finish" else="warnNoDeliveryAvailable"/> </decision-state> ………………………. <end-state id="finish"> <output-mapper> <mapping source="flowScope.customer“ target="customer"/> </output-mapper> </end-state>
  35. 35. Subflows A subflow state is a state that references another flow. When a flow enters a subflow state, the current flow is suspended and the referencedflow is executed, analogous to method calls in Java. <subflow-state id="getCustomerInfo" flow="CustomerInfo-flow" > <attribute-mapper> <output-mapper> <mapping source="customer" target="flowScope.order.customer"/> </output-mapper> </attribute-mapper> <transition on="finish" to="showOrder" /> </subflow-state> In above example, the getCustomerInfo state is a subflow state that references the flownamed CustomerInfo-flow. In the CustomerInfo-flow, the flow-scoped Customer object is mapped to an outputvariable named customer, while in the <subflow-state> that output variable is mapped tothe customer property of the order flow’s flow-scoped Order object. Further, the <start-state> which referred to the askForPhoneNumber state, refers to thegetCustomerInfo state of CustomerInfo-flow were askForPhoneNumber is the start state: <start-state idref="getCustomerInfo" />
  36. 36. Integrating with Jakarta Struts Spring Web Flow integrates into Struts through FlowAction, a StrutsAction implementation similar to FlowController in Spring MVC. FlowAction is a Struts-specific front controller for Spring Web Flow. It is configured in <action-mappings> section of strutsconfig.xml using<action> tag as below: <action path="/flow“ name="actionForm“ scope="request" type="org.springframework.webflow.executor.struts.FlowAction"/> FlowAction uses parameters to guide the flow which are bound toSpringBindingActionForm, an ActionForm implementation configuredas follows: <form-bean name="actionForm" type= "org.springframework.web.struts. ➥ SpringBindingActionForm"/> The name of the <form-bean> is the same as the name of the <action> toallow Struts to know the SpringBindingActionForm to be used to bindparameters for FlowAction. In a Struts-based flow a <view-state>’s view refers to a Struts <forward>.