From 46a0e7da27a21d8834f7a87af67a581f48ea90c1 Mon Sep 17 00:00:00 2001 From: Erwin Vervaet Date: Thu, 1 Feb 2007 17:02:45 +0000 Subject: [PATCH] Added documentation for flowlauncher and itemlist samples as contributed by Ross. --- .../docs/reference/src/practical.xml | 400 +++++++++++++++++- 1 file changed, 394 insertions(+), 6 deletions(-) diff --git a/spring-webflow/docs/reference/src/practical.xml b/spring-webflow/docs/reference/src/practical.xml index 98b4f5c0..8284e34d 100644 --- a/spring-webflow/docs/reference/src/practical.xml +++ b/spring-webflow/docs/reference/src/practical.xml @@ -35,15 +35,19 @@ NumberGuess - demonstrates use of stateful middle-tier components to carry out business logic. + + + Flowlauncher - demonstrates all the possible ways to launch and resume flows. + + + + + Itemlist - demonstrates REST-style URLs and inline flows. + + Sellitem - demonstrates a wizard with conditional transitions, flow scope, flow execution redirects, and continuations. - - Flowlauncher - demonstrates all the possible ways to launch and resume flows. - - - Itemlist - demonstrates REST-style URLs and inline flows. - Phonebook-Portlet - the phonebook sample in a Portlet environment (notice how the flow definitions do not change). @@ -971,4 +975,388 @@ enum GuessResult { + + Flowlauncher Example + + Overview + + Flowlauncher demonstrates two different ways one web flow can launch + another - by redirecting to it or by launching it as a subflow. + Flowlauncher has two flows: Sample A and Sample B. As a root level + flow Sample A either transitions to B through a subflow state or + redirects to B in its end state. + + + + Web.xml + + The web.xml configuration maps "*.htm" requests to the flowlauncher servlet - + a regular Spring MVC DispatcherServlet: + +<servlet> + <servlet-name>flowlauncher</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> +</servlet> + +<servlet-mapping> + <servlet-name>flowlauncher</servlet-name> + <url-pattern>*.htm</url-pattern> +</servlet-mapping> + + + + + Spring MVC Context + + The Spring MVC web context (WEB-INF/flowlauncher-servlet.xml) defines one controller bean: + +<bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController"> + <property name="flowExecutor" ref="flowExecutor" /> +</bean> + + FlowController is a Web Flow extension of Spring MVC's AbstractController. + It contains a FlowExecutor and directs incoming requests for one + or more managed flow executions to it. The FlowExecutor bean is configured + in the same context: + +<!-- Launches new flow executions and resumes existing executions. --> +<flow:executor id="flowExecutor" registry-ref="flowRegistry"/> + +<!-- Creates the registry of flow definitions for this application --> +<flow:registry id="flowRegistry"> + <flow:location path="/WEB-INF/sampleA.xml" /> + <flow:location path="/WEB-INF/sampleB.xml" /> +</flow:registry> + + A single FlowController may direct all flows for an application serving as + a gateway to Web Flow. Based on the above definitions the flows + sampleA and sampleB can be invoked as follows: + +/swf-flowlauncher/flowController.htm?_flowId=sampleA +/swf-flowlauncher/flowController.htm?_flowId=sampleB + + The welcome index.html file for the web application invokes + the flows and passes additional input using either a URL link + or a form submit. + + + + Sample A Web Flow + + The Sample A web flow (/WEB-INF/sampleA.xml) begins with an input mapping declaration: + +<input-mapper> + <mapping source="input" target="flowScope.input" /> +</input-mapper> + + This declaration reads "when a new execution of this flow starts map the + input attribute named input into a flowScope attribute + also named input". Spring Web Flow will automatically provide the request + parameters as input to the flow when launching a new flow execution. + Following this declaration the input + request parameter will remain available for the duration of the flow. + + + There are 3 states in this flow: the start state, the end state, and a subflow + state. The start state is a view state - it will display a JSP page and allow + the user to make a choice. The subflow state initiates Sample B as a + subflow of the current flow - subflows give the ability to compose independent + modules together to compose complex controller workflows. And the end state + launches Sample B by redirecting to it. + + + The subflow state launches B with the following input attribute declaration. + This declaration reads "pass the value of the flow-scoped attribute named + input as an attribute also named input + to subflow B. + +<attribute-mapper> + <input-mapper> + <mapping source="flowScope.input" target="input" /> + </input-mapper> +</attribute-mapper> + + The next line is a transition defining how to respond + when the subflow ends: advance back to the start state for Sample A. + +<transition on="end" to="aPage" /> + + + + The end state demonstrates how to redirect to Sample B upon completion of + the root level flow Sample A: + +<end-state id="endAndLaunchB" view="flowRedirect:sampleB?input=${requestParameters.input}" /> + + This declaration causes A to be terminated and B to start + with the given requst input parameter. + + + + Sample B Web Flow + + The flow Sample B (/WEB-INF/sampleB.xml) - used as a subflow in Sample A has two + simple states: a view state and an end state. From the view state "bPage" the + flow transitions to the end state: + +<view-state id="bPage" view="bPage"> + <transition on="end" to="end" /> +</view-state> + +<end-state id="end" /> + + The "id" attribute of the end state matches the "on" attribute of the + transition in the outer flow's subflow state, which the outer flow + uses to resume itself. + + + Also notice how bPage.jsp makes a check to detect if Sample B is + running as a subflow of Sample A or if it is running as a top-level flow: + +<c:if test="${!flowExecutionContext.activeSession.root}"> + + + The FlowExecutionContext object is exposed to the views (JSPs) + to make information like this available during response rendering. + + + + Iitemlist Example + + Overview + + Itemlist demonstrates how to configure a FlowExecutor with an argument handler + enabling it to process REST-style requests where the name of the target + flow is in the URL instead of a _flowId request parameter. + The example also demonstrates inner flows as well as how an output parameter + can be passed from a subflow to a parent flow. + Finally, it serves as an illustration of how to configure Spring Web Flow + using classic Spring 1.x bean definitions. + + + + Web.xml + + The web.xml configuration maps "/app/*" requests to the itemlist servlet - + a regular Spring MVC DispatcherServlet: + +<servlet> + <servlet-name>itemlist</servlet-name> + <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> +</servlet> + +<servlet-mapping> + <servlet-name>itemlist</servlet-name> + <url-pattern>/app/*</url-pattern> +</servlet-mapping> + + + + + Spring MVC Context + + The Spring MVC web context (/WEB-INF/itemlist-serlvet.xml) defines one controller + and one URL handler mapping: + +<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> + <property name="alwaysUseFullPath" value="true" /> + <property name="mappings"> + <value>/app/**/**=flowController</value> + </property> +</bean> + +<bean id="flowController" class="org.springframework.webflow.executor.mvc.FlowController"> + <property name="flowExecutor" ref="flowExecutor" /> + <property name="argumentHandler"> + <bean class="org.springframework.webflow.executor.support.RequestPathFlowExecutorArgumentHandler" /> + </property> +</bean> + + All requests with a servlet path matching "/app/**/**" are mapped to the "flowController" bean. + The FlowController is a Web Flow extension of Spring MVC's AbstractController delegating + requests to one or more managed web flows. It acts as gateway to Web Flow defined control + logic and a single instance can serve the application. + + + The usual way to launch a specific web flow is to pass the _flowId request parameter. + However, this example is configured with a RequestPathFlowExecutorArgumentHandler + for processing REST-style URL's. + Requests for services built around the REST concept are encoded in the URL + and not as query string parameters. The way to invoke a web flow with + this argument handler is to follow: + +http://${host}/${context path}/${dispatcher path}/${flowId} + + + + The FlowController is configured with a flowExecutor and flowRegistry beans containing + two web flows - itemlist and itemlist-alternate: + +<!-- Launches new flow executions and resumes existing executions: Spring 1.2 config version --> +<bean id="flowExecutor" class="org.springframework.webflow.config.FlowExecutorFactoryBean"> + <property name="definitionLocator" ref="flowRegistry"/> +</bean> + +<!-- Creates the registry of flow definitions for this application: Spring 1.2 config version --> +<bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean"> + <property name="flowLocations"> + <list> + <value>/WEB-INF/itemlist.xml</value> + <value>/WEB-INF/itemlist-alternate.xml</value> + </list> + </property> +</bean> + + The FlowRegistry and FlowExecutor are defined with Spring 1.2 compatible bean definitions. + However, starting with Spring 2.0 Web Flow also offers the + custom tags flow:registry and flow:executor, which are more + readable and less verbose. + + + Based on the above web context definition use the following URL's to invoke + the itemlist or the itemlist-alternate web flows: + +/swf-itemlist/app/itemlist +/swf-itemlist/app/itemlist-alternate + + + + Also defined in itemlist-servlet.xml are three "action" beans - createItemAction, + addItemAction, and mapItemAction, which will be referenced from action states + in the web flow definitions. + + + + Itemlist Web Flow + + The itemlist flow allows adding items to a list. There are + two view states - displayItemList and displayItem, and two action states - + createItem and addItem. + + + The displayItemList view state resolves to /WEB-INF/jsp/itemList.jsp, which + lists all items on the list and displays an "Add" button with the + name "_eventId_add". The name of the button indicates the + event id to use for deciding where to transition to next. + Also, notice that instead of posting a "_flowId" parameter + the JSP sets the form action to the value of flowExecutionKey - + a value automatically made available in the page + context by Web Flow: + +<form action="${flowExecutionKey}" method="post"/> + + + + When the form submits an event with the "_eventId_add" button + the displayItemList view state transitions to the + createItem action state. + +<view-state id="displayItemlist" view="itemlist"> + <transition on="add" to="createItem" /> +</view-state> + +<action-state id="createItem"> + <action bean="createItemAction" /> + <transition on="success" to="displayItem" /> +</action-state> + + + + The "createItemAction" bean is declared in the Spring MVC context + (/WEB-INF/itemlist-servlet.xml). It simply returns "success", which + causes a transition to the displayItem view state. + + + The next two states displayItem and addItem allow adding an item to the + list variable declared at the top of the flow: + +<var name="list" class="java.util.ArrayList" /> + + The "addItemAction" bean is also declared in the Spring MVC context. + It performs the add by accessing the list in flow scope and + the item to be added from the request parameters as follows: + +Collection list = context.getFlowScope().getRequiredCollection("list"); +String data = context.getRequestParameters().get("data"); +if (data != null && data.length() > 0) { + list.add(data); +} + + For any outcome the addItem state transitions back to the initial + displayItemList state using an event pattern match: + +<action-state id="addItem"> + <action bean="addItemAction" /> + <transition on="*" to="displayItemlist" /> +</action-state> + + + + + Itemlist-alternate Web Flow + + The Itemlist-alternate web flow (/WEB-INF/itemlist-alternate.xml) + has functionality equivalent to that of itemlist but instead uses + a subflow for selecting individual items. + The "addItem" state is a subflow state + invoking an inline flow called "item" (also defined in itemlist-alternate.xml) + accepting an output parameter from the subflow and adding the + output parameter to a flow-scoped list variable: + +<subflow-state id="addItem" flow="item"> + <attribute-mapper> + <output-mapper> + <mapping source="item" target-collection="flowScope.list" /> + </output-mapper> + </attribute-mapper> + <transition on="finish" to="displayItemlist" /> +</subflow-state> + + An output-mapper is used to pass results from a subflow to a parent flow. + The above declaration defines an expectation on the subflow to return + an output parameter called "item". Accordingly the end state for the + inline flow has this output mapping returning a parameter called "item": + +<end-state id="finish"> + <output-mapper> + <mapping source="flowScope.item" target="item" /> + </output-mapper> +</end-state> + + With the above declarations we see how a subflow can pass output + parameters back to its parent flow. The remaining question is + what sets "flowScope.item" which appears for the first time + in the end state of the subflow? + + + The answer lies in the "mapItemAction" bean invoked between the + view state and the end state in the subflow: + +<action-state id="mapItem"> + <action bean="mapItemAction" /> + <transition on="success" to="finish" /> +</action-state> + + The mapItemAction bean was defined in the itemlist-servlet.xml web context + and is an istance of Web Flow's AttributeMapperAction. The purpose + of AttributeMapperAction is to invoke an AttributeMapper and to perform + mappings between two attribute sources. The AttributeMapper with which + the mapItemAction bean is configured is an instance of DataMapper. It + adds the following mapping: + +addMapping(mapping.source("requestParameters.data").target("flowScope.item").value()); + + With this declaration in place each time the AttributeMaperAction is + invoked it will create the flowScoped variable "item" based on the value + of the "data" request parameter. Note that AttributeMapper is + Web Flow API for the <attribute-mapper> declarations used above + to pass data from the inner subflow to the parent flow. + + + Once the inner subflow flow has completed the item is passed to the parent flow + as an output parameter, which adds it to its flow-scoped list and transitions + to the initial "displayItemList" state. + + +