diff --git a/spring-webflow/docs/reference/src/defining-flows.xml b/spring-webflow/docs/reference/src/defining-flows.xml new file mode 100644 index 00000000..bc6bd102 --- /dev/null +++ b/spring-webflow/docs/reference/src/defining-flows.xml @@ -0,0 +1,60 @@ + + + Defining Flows + + Introduction + + This chapter begins the Users Section of this guide. + It shows how to implement flows using the flow definition language. + By the end of this chapter, you should have a good understanding of language constructs and capable of authoring a flow definition. + + + + What is a Flow? + + A flow encapsulates a reusable sequence of steps that can execute in different contexts. + Below is a Garrett Information Architecture diagram illustrating a reference to a flow that encapsulates the steps of a hotel booking process: + + + + + + + + + + A BookHotel Flow Definition + + + + + What is the makeup of a typical Flow? + + In Spring Web Flow, a flow consists of a series of steps called "states". + Entering a state typically results in a page being displayed to the user. + On the page, user events occur that are handled by that state. + These events can trigger transitions to other states which result in page navigations. + + + The example below shows the structure of the book hotel flow referenced in the previous diagram: + + + + + + + + + + Hotels Site Diagram that references a "Book Hotel" flow + + + + + How are Flows authored? + + Flows are authored by web application developers using a XML-based flow definition language. + The next steps of this guide will walk you through the elements of this language. + + + \ No newline at end of file diff --git a/spring-webflow/docs/reference/src/flow-definition.xml b/spring-webflow/docs/reference/src/flow-definition.xml deleted file mode 100644 index b1b74c6a..00000000 --- a/spring-webflow/docs/reference/src/flow-definition.xml +++ /dev/null @@ -1,2462 +0,0 @@ - - - Flow definition - - Introduction - - Spring Web Flow allows developers to build reusable, self-contained controller modules - called flows. A flow defines a user dialog that responds to user events to drive - the execution of application code to complete a business goal. - - - Flows are defined declaratively using a rich domain-specific language (DSL) - tailored to the problem domain of UI flow. Currently, XML and Java-based - forms of this language are provided. - - - This chapter documents Spring Web Flow's core flow definition language. You will - learn the core domain constructs of the system and how those constructs are - representable in an externalized XML form. - - - - FlowDefinition - - A flow definition is a instance of org.springframework.webflow.definition.FlowDefinition. - This is the central domain artifact representing the definition of a user dialog or task. - - - A flow definition consists of a set of one or more states, where each state defines a step in - the flow that when entered executes a behavior. What behavior is executed is - a function of the state's type and configuration. The outcome of a state's - execution, called an event, is used by the flow to drive a state transition. - - - Exactly one of a flow's states is the startState - that defines the starting point of the flow. Optionally, a flow can have one or more end states - defining the ending points of the flow. - - - An example definition of a simple flow to carry out a search process is shown graphically below: - - - - - - - - - - Search Flow - - - - The default FlowDefinition implementation in Spring Web Flow is - org.springframework.webflow.engine.Flow. Its configurable properties are - summarized below: - - - Flow properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - id - The identifier of the flow definition, typically unique to all other flows of the application. - - 1 - - - - attributes - Additional custom attributes about the flow. - - 0..* - - None - - - states - The steps of the flow. - - 1..* - - - - startState - The starting point of the flow. - - 1 - - - - variables - The set of flow instance variables to create each time an execution of the flow is started. - - 0..* - - Empty - - - inputMapper - - The service responsible for mapping flow input provided by the client each time an - execution of the flow is started. - - - 0..1 - - Null - - - startActions - The list of actions to execute each time an execution of the flow is started. - - 0..* - - Empty - - - endActions - The list of actions to execute each time an execution of the flow ends. - - 0..* - - Empty - - - outputMapper - - The service responsible for mapping flow output to expose to the client each time an execution of the flow ends. - - - 0..1 - - Null - - - globalTransitions - The set of transitions shared by all states of the flow. - - 0..* - - Empty - - - exceptionHandlers - An ordered set of handlers to be applied when an exception is thrown within a state of the flow. - - 0..* - - Empty - - - -
- - Below is a high level example of how these properties can be configured in XML form - or directly in Java code. - - - XML-based Flow template - - <?xml version="1.0" encoding="UTF-8"?> - <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-1.0.xsd"> - - <attribute .../> - - <var .../> - - <input-mapper .../> - - <start-actions> - ... - </start-actions> - - <start-state idref="yourStartingStateId"/> - - <-- your state definitions go here --> - - <global-transitions> - ... - </global-transitions> - - <end-actions> - ... - </end-actions> - - <output-mapper .../> - - <exception-handler .../> - - </flow> - - - - Java Flow API example - - Flow flow = new Flow("id"); - flow.getAttributeMap().put("name", "value"); - flow.addState(...); - flow.setStartState("startingPoint"); - flow.addVariable(...); - flow.setInputMapper(...); - flow.getStartActionList().add(...); - flow.getEndActionList().add(...); - flow.setOutputMapper(...); - flow.getGlobalTransitionSet().add(...); - flow.getExceptionHandlerSet().add(...); - - - A Flow is typically built by a FlowBuilder rather than assembled - by hand. The flow building subsystem is contained within the - org.springframework.webflow.engine.builder package. - The XML Flow Builder and spring-webflow.xsd schema are located - within the org.springframework.webflow.engine.builder.xml package. - The XML-based format is currently the most popular way to define flows, though - Groovy-based and Java-based formats are emerging. - - -
- - StateDefinition - - A StateDefinition defines the behavior for a step of a FlowDefinition. - The base implementation class for all Flow state types is org.springframework.webflow.engine.State. - This abstract class defines common properties applicable to all state types, which include: - - - State properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - id - The id of the state, unique to its containing flow definition. - - 1 - - - - owner - The owning flow definition. - - 1 - - - - attributes - Additional custom attributes about the state. - - 0..* - - None - - - entryActions - The list of actions to execute each time the state is entered. - - 0..* - - Empty - - - exceptionHandlers - An ordered set of handlers to be invoked when an exception is thrown within the state. - - 0..* - - Empty - - - -
-
- - Transitionable State - - A central subclass of State is org.springframework.webflow.TransitionableState. - This abstract class defines common properties applicable to all state types that execute - transitions to other states in response to events. These properties include: - - - TransitionableState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - transitions - The eligible paths out of this state. - - 1..* - - - - exitActions - The list of actions to execute each time this state is exited. - - 0..* - - Empty - - - -
- - Below is a mock flow definition snippet showing how properties may be configured for - a TransitionableState in XML and in Java code: - - - XML-based state template - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="myStateId"/> - - <xxx-state id="myStateId"> - <attribute name="..." value="..."/> - - <entry-actions> - ... - </entry-actions> - - <transition on="..." to="..."/> - <transition on-exception="..." to="..."/> - - <exit-actions> - ... - </exit-actions> - - <exception-handler .../> - </xxx-state> - - </flow> - - - - Java state API example - - Flow flow = new Flow("id"); - TransitionableState state = new XXXState(flow, "stateId"); - state.getAttributeMap().put("name", "value"); - state.getEntryActionList().add(...); - state.getTransitionSet().add(...); - state.getExitActionList().add(...); - - - A State is typically constructed by a FlowArtifactFactory, used by - a FlowBuilder during flow assembly. The flow building subsystem is contained within the - org.springframework.webflow.engine.builder package. - - -
- - TransitionDefinition - - A transition takes a flow from one state to another, defining a path through the flow. - This is modeled using a TransitionDefinition. - - - Recall that all TransitionableStates have a set of one or more transitions, each defining a - path to another state in the flow (or a recursive path back to the same state). - When a transitionable state is entered, it executes a behavior. - For example, a transitionable state called "Display Form" may display a form to the user - and wait for user input. The outcome of the state's execution, called an event, is used to drive execution of - one of the state's transitions. For example, the user may press the form submit button which - signals a submit event that matches the transition to - the "Process Submit" state. - - - This event-driven transition execution process is shown graphically below: - - - - - - - - - - Transition execution - - - - The transition definition implementation is defined by an instance of - org.springframework.webflow.engine.Transition. - Its properties are summarized below: - - - Transition properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - attributes - Additional attributes describing the transition. - - 0..* - - None - - - matchingCriteria - The strategy that determines if the transition matches on an event occurrence. - - 1 - - Always matches - - - executionCriteria - The strategy that determines if the transition, once matched, is allowed to execute. - - 1 - - Always allowed - - - targetStateResolver - - The strategy that resolves the target state of the transition. - Most transitions always resolve to the same target state. - This strategy allows for dynamic resolution. - - - 1 - - - - - -
- - Below is a high-level example of how a Transition can be configured in XML form - or directly in Java code. - - - Transition XML template - - <transition on="event" to="targetState"> - <attribute ... /> - <action ... /> - </transition> - - - - Transition Java API example - - Transition transition = new Transition("targetState"); - transition.getAttributeMap().put("name", "value"); - transition.setMatchingCriteria(new EventIdTransitionCriteria("event")); - transition.setExecutionCriteria(...); - - - - Action transition execution criteria - - In the XML transition template above, note the support for the action element within the transition element. - - - A transition may be configured with one or more actions that execute before the transition itself - executes. If one or more of these actions do not complete successfully, the transition will not be allowed. - This execution criteria makes it possible to execute arbitrary logic - after a transition is matched but before it is executed. This is useful when you want to execute - event post-processing logic. A good example is executing form data binding and validation behavior - after a form submit event. - - - - Dynamic transitions - - A transition's target state resolver can be configured to dynamically calculate the target state. For example: - - - <transition on="back" to="${flowScope.lastViewStateId}" /> - - - This will transition the flow to the state resolved by evaluating the - flowScope.lastViewStateId expression. - - - - Global transitions - - As outlined, one or more transitions are added to all TransitionableState types, - attached at the state-level. Optionally, transitions may also be added at the - flow-level where they are shared by all states. These shared - transitions are called global transitions. - - - When an event is signaled in a transitionable state, the state will first try and - match one of its own transitions. If there is no match at the state level, the set of - global transitions will be tested. If there still is no match, - a NoMatchingTransitionException will be thrown. - - - Global transitions are useful in situations where many states of the flow share - the same transitional criteria. For example, consider a navigation menu that displays - alongside each view of a flow. Logic to process navigation menu events is needed - by all view states. This is the problem global transitions are designed to solve. - - - Global transitions - XML example - - The following example shows transitions defined at the state level, as well as - global transitions defined at the flow level. - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="state1"/> - - <xxx-state id="state1"> - <transition on="localEvent1" to="state2"/> - </xxx-state> - - <xxx-state id="state2"> - <transition on="localEvent1" to="state1"/> - </xxx-state> - - <global-transitions> - <transition on="globalEvent1" to="state1"/> - <transition on="globalEvent2" to="state2"/> - </global-transitions> - - </flow> - - - In this mock example, state1 defines one transition and also inherits - the two others defined within the global-transitions element. - Any other states defined within this flow would also inherit those global transitions. - - - This example is shown graphically below: - - - - - - - - - - Global transitions - - - - - - Transition executing exception handlers - - The <transition/> element contains an exclusive on-exception - attribute used to specify an exception-based criteria for transition execution. This allows you to - transition the flow to another state on the occurrence of an exception. Transition executing exception handlers - may be attached at the state and flow levels. - - - State exception handling - XML example - - The following example illustrates a state-level transition executing exception handler: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="state1"/> - - <xxx-state id="state1"> - <transition on="event1" to="state2"/> - <transition on-exception="example.MyBusinessException" to="state3"/> - </xxx-state> - - ... - - </flow> - - - In this example, state1 defines one transition and an exception handler - which executes a transition to state3 if a MyBusinessException - is thrown within the state. The handled exception will be put into flash scope under the - key stateException, where it will be automatically exposed to the next view (typically an error view). - - - - Flow exception handling - XML example - - The following example illustrates a flow-level transition executing exception handler: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="state1"/> - - <xxx-state id="state1"> - <transition on="event1" to="state2"/> - </xxx-state> - - <xxx-state id="state2"/> - - <global-transitions> - <transition on-exception="example.MyBusinessException" to="state3"/> - </global-transitions> - - ... - - </flow> - - - In this example, the exception handler is defined as a global transition. This reads "any time - a MyBusinessException occurs during flow execution, transition the flow - to state3". - - - Exception handlers attached at the state level take precedence over those defined at the flow level. - This is illustrated by the following example: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="state1"/> - - <xxx-state id="state1"> - <transition on="event1" to="state2"/> - <transition on-exception="example.MyBusinessException" to="state4"/> - </xxx-state> - - <xxx-state id="state2"/> - - <global-transitions> - <transition on-exception="example.MyBusinessException" to="state3"/> - </global-transitions> - - ... - - </flow> - - - In this example, if MyBusinessException is thrown in state1 the - flow will transition to state4. For any other state, the flow will transition to state3. - - - - - Custom exception handlers - - Custom, user-defined exception handlers may be attached at the flow and state levels by using the - exception-handler element. This element delegates to Spring to locate - the custom exception handler instance with the specified bean name. - - - An example of attaching a custom exception handler is shown below: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="state1"/> - - <xxx-state id="state1"> - <transition on="event1" to="state2"/> - <exception-handler bean="myCustomStateExceptionHandler"/> - </xxx-state> - - <xxx-state id="state2"/> - - <global-transitions> - <exception-handler bean="myCustomFlowExceptionHandler"/> - </global-transitions> - - <import resource="flow-beans.xml"/> - - </flow> - - - flow-beans.xml - - <bean id="myCustomStateExceptionHandler" class="example.CustomFlowExecutionExceptionHandler"/> - <bean id="myCustomFlowExceptionHandler" class="example.AnotherCustomFlowExecutionExceptionHandler"/> - - - - Custom exception handlers must implement the org.springframework.webflow.engine.FlowExecutionExceptionHandler interface. - - -
- - Concrete state types - - Spring Web Flow has five (5) built-in concrete state types, all contained within the - org.springframework.webflow.engine package. These states execute common - controller behaviors including: - - allowing the user to participate in a flow (ViewState) - executing business application code (ActionState) - making a flow routing decision (DecisionState) - spawning another flow as a subflow (SubflowState) - terminating a flow (EndState) - - - - Each of these state types, with the exception of EndState, is transitionable. - This hierarchy is illustrated below: - - - - - - - - - - FlowDefinition class diagram - - - - As you will see, with these five basic state types you can develop rich controller modules. - - - ViewState - - When entered, a view state allows the user (or other external client) to participate - in a flow. This participation process goes as follows: - - - - The entered view state renters a view to issue a response to the caller. - - - - - The flow execution 'pauses' in this state, and control is returned to the calling system. - - - - - After some 'think time', the user signals an input event to resume the flow execution - from the 'paused' point. - - - - - - Spring Web Flow gives you full control over the view selection process and, on resume, - how a view state responds to a user input event. - - - The properties of a org.springframework.webflow.engine.ViewState are summarized below: - - - ViewState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - viewFactory - The strategy that makes the view selection when this state is entered. - - 0..1 - - Null - - - renderActions - - The list of actions to execute each time a renderable view selection is made. - Allows for execution of pre-render logic. - - - 0..* - - Empty - - - -
- - The org.springframework.webflow.execution.ViewFactory type is an interface, - encapsulating knowledge about a particular view rendering technology. - with the flow. Concrete subtypes exist for each of the supported view technologies. - These subtypes are summarized below: - - - Concrete ViewFactory types - - - - - - Type - Description - - - - - JsfViewFactory - Requests the rendering of Java Server Faces (JSF) view. - - - MvcViewFactory - - Requests the rendering of a Spring MVC view. - - - - -
- - ViewState class diagram - - The class diagram below shows the ViewState and the associated types used to carry - out the view selection process (TODO - needs updating for 2.0): - - - - - - - - - - ViewState class diagram - - - - - ViewState XML - application view selection - - The following example shows a view-state definition in XML that makes an application view - selection when entered, selecting the searchForm view for display and, on resume, responding to - two possible user input events (submit and cancel) in different ways: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="displaySearchForm"/> - - <view-state id="displaySearchForm" view="searchForm"> - <transition on="submit" to="processFormSubmission"/> - <transition on="cancel" to="processCancellation"/> - </view-state> - - ... - - </flow> - - - View name expressions may also be specified for the view attribute to - achieve runtime view name calculation. - For example, view="${requestScope.calculatedViewName}". - - - - ViewState API - application view selection - - The following example shows the equivalent view state definition using - the FlowBuilder API: - - - public class SearchFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - addViewState("displaySearchForm", "searchForm", - new Transition[] { - transition(on("submit"), to("processFormSubmission")), - transition(on("cancel"), to("processFormCancellation")) - } - ); - ... - } - } - - - - ViewState XML - flow execution redirect - - The following example illustrates a view-state definition in XML that makes an - flow execution redirect selection when entered, redirecting to the - yourList view for display. - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="displayList"/> - - <view-state id="displayList" view="redirect:yourList"> - <transition on="add" to="addListItem"/> - </view-state> - - ... - - </flow> - - - This example is called a flow execution redirect because the application view selected - is rendered only after a redirect to the flow execution. The redirect request is sent to a - URL that refreshes the flow execution paused in the displayList - view state. Refresh then triggers the rendering of the yourList application view - on the next request into the server. - - - POST+REDIRECT+GET in Spring Web Flow - - The above example is one way to achieve the POST+REDIRECT+GET pattern in Spring Web Flow. - When the redirect is performed, the GET request issued hits a stable flow execution URL - which remains active for the duration of the conversation. This URL may be freely refreshed. - Browser navigational buttons may be used freely without browser warnings. - - - The execution attribute alwaysRedirectOnPause, which enforces this pattern by default, - is discussed later in this document. In that case, each time a view state is entered a redirect is always performed. - - - - - ViewState API - flow execution redirect - - The following example shows the equivalent view state definition using the FlowBuilder API: - - - public class SearchFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - addViewState("displayList", viewSelector("redirect:yourView"), - transition(on("add"), to("addListItem")) - ); - ... - } - } - - - - ViewState XML - null view - - The following example illustrates a view-state definition in XML that makes a - null view selection when entered. This causes no additional response to be issued. - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="displayPdf"/> - - <view-state id="displayPdf"> - <render-actions> - <action bean="pdfWriter" method="write"/> - </render-actions> - </view-state> - - ... - - </flow> - - - - FlowDefinitionRedirect and ExternalRedirect - - The FlowDefinitionRedirect and ExternalRedirect are not - generally used by a view state. They are typically used by an end state, either to start - a new independent flow or redirect to an arbitrary external URL. - Examples are provided in the discussion of the end state. - - - - ViewState XML - form state behavior - - The following example illustrates a view-state definition in XML that encapsulates - typical "form state" behavior. - - - Consider the requirements of typical input forms. Most forms require pre-render or - setup logic to execute before the form is displayed. For example, such logic might - load the backing form object from the database, install formatters for formatting - form field values, and pull in supporting form data needed to populate drop-down menus. - - - In addition, most forms require post-back or submission logic - to execute when the form is submitted. This logic typically involves binding form input to the - backing form object and performing type conversion and data validation. - - - This "form state" behavior of form setup, display, and post-back is handled elegantly in Spring Web Flow - by the capabilities of the view-state construct. See below: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="displayForm"/> - - <view-state id="displayForm" view="form"> - <render-actions> - <action bean="formAction" method="setupForm"/> - <action bean="formAction" method="loadFormReferenceData"/> - </render-actions> - <transition on="submit" to="saveForm"> - <action bean="formAction" method="bindAndValidate"/> - </transition> - </view-state> - - ... - - </flow> - - - This reads "when this flow starts enter the displayForm state - to execute the setupForm and loadFormReferenceData methods - before rendering the form view. On submit, - transition to the saveForm state if the bindAndValidate method executes successfully." - - -
- - ActionState - - When entered, an action state executes business application code, then responds to the result of that - execution by deciding what state in the flow to enter next. Specifically: - - - - The entered action state executes an ordered list of one or more - org.springframework.webflow.execution.Action - instances. This Action interface is the central abstraction that - encapsulates the execution of a logical unit of application code. - - - - - The state determines if the outcome of the first action's execution matches a - transition. If there is a match, the transition is executed. If there is no match, - the next action in the list is executed. This process continues until a transition is - matched or the list of actions is exhausted. - - - - - - Spring Web Flow gives you full control over implementing your own actions and configuring when they should be invoked - within the lifecycle of a flow. The system can also automatically adapt methods on - your existing application objects (POJOs) to the Action interface in a non-invasive manner. - This means in many cases you can implement your flows without needing to develop custom glue code to bind SWF - to your service layer operations. - - - The properties of a org.springframework.webflow.engine.ActionState are summarized below: - - - ActionState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - actions - The ordered list of actions to execute when the state is entered. - - 1..* - - - - - -
- - Action execution points - - As outlined, the ActionState is the dedicated state type for invoking one - or more actions and responding to their result to drive a state transition. There are - also other points within the lifecycle of a flow where a chain of actions can be executed. - At all of these points, the only requirement is that these actions implement the central - org.springframework.webflow.execution.Action interface. - - - - Other points in a Flow where an Action can be executed, and how those points - can be defined in a XML-based Flow definition. - - - - - - - - Point - Description - XML Configuration Element - - - - - on flow start - - Each time a new flow session starts. - - - A flow's <start-actions/> - - - - on state entry - - Each time a state enters. - - - A state's <entry-actions/> - - - - on transition - - Each time a state transition is matched but before it is executed. - - - A transition <action/> - - - - on state exit - - Each time a transitionable state exits. - - - A transitionable state's <exit-actions/> - - - - before view rendering - - Each time a renderable view selection is made. - - - A view state's <render-actions/> - - - - on flow end - - Each time a flow session terminates. - - - A flow's <end-actions/> - - - - -
- - - - The other points above where actions may be executed do not - allow you to execute a state transition in response to the action result event. - If you need such flow control you must execute the action from within an action state. - - - -
- - Action attributes - - An Action may be annotated with attributes by wrapping the Action - in a decorator, an instance of org.springframework.webflow.engine.AnnotatedAction. - These attributes may provide descriptive characteristics, or may be used to affect - the action's execution in a specific usage context. - - - Support for setting several common attributes is provided for convenience. These include: - - - Common Action attributes - - - - - - Attribute name - Description - - - - - caption - - A short description about the action, suitable for display as a tool-tip. - - - - description - - A long description about the action, suitable for display in a text box. - - - - name - - The name of the action, used to qualify the action's result event. - For example, an Action named placeOrder that returns success - would be assigned a result event identified by placeOrder.success. - This allows you to distinguish logical execution outcomes by action, useful when - invoking multiple actions as part of a chain. - - - - method - - The name of the target method on the Action instance to invoke to carry out execution. - This facilitates multiple action methods per Action instance, - supported by the org.springframework.webflow.action.MultiAction. - - - - -
-
- - ActionState class diagram - - The class diagram below shows the ActionState and the associated types used to carry - out the action execution process: - - - - - - - - - - ActionState class diagram - - - - - ActionState XML - simple action execution - - The following example constructs an ActionState definition from - XML that executes a single action when entered and then responds to its result: - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="executeSearch"/> - - <action-state id="executeSearch"> - <action bean="searchAction"/> - <transition on="success" to="displayResults"/> - </action-state> - - ... - - </flow> - - This state definition reads "when the executeSearch - state is entered, execute the searchAction. On successful execution, - transition to the displayResults state." - - - The binding between the searchAction id and an - Action implementation is made at Flow build time - by querying a service locator, typically a Spring BeanFactory. For example: - - <beans> - <bean id="searchAction" class="example.webflow.SearchAction"/> - </beans> - - ... binds the searchAction action identifier to a singleton instance of the - example.webflow.SearchAction class. - - - A simple SearchAction implementation might look like this: - - public class SearchAction implements Action { - private SearchService searchService; - - public SearchAction(SearchService searchService) { - this.searchService = searchService; - } - - public Event execute(RequestContext context) { - // lookup the search criteria in "flow scope" - SearchCriteria criteria = - (SearchCriteria)context.getFlowScope().get("criteria"); - - // execute the search - Collection results = searchService.executeSearch(criteria); - - // set the results in "request scope" - context.getRequestScope().put("results", results); - - // return "success" - return new Event(this, "success"); - } - } - - - - - ActionState API - standard action - - The following example constructs the equivalent action state definition using - the FlowBuilder API: - - - public class SearchFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - ... - addActionState("executeSearch", action("searchAction"), - transition(on("success"), to("displayResults"))); - ... - } - } - - - - ActionState XML - multi action - - The next example constructs an ActionState definition from XML that - executes a single action method on a org.springframework.webflow.action.MultiAction - and then responds to its result: - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="executeSearch"/> - - <action-state id="executeSearch"> - <action bean="searchAction" method="executeSearch"/> - <transition on="success" to="displayResults"/> - </action-state> - - ... - - </flow> - - This state definition reads "when the executeSearch - state is entered, call the executeSearch method on the - searchFlowAction. On successful execution, - transition to the displayResults state." - - - A SearchAction implementation containing multiple action methods - might look like this: - - public class SearchAction extends MultiAction { - private SearchService searchService; - - public SearchAction(SearchService searchService) { - this.searchService = searchService; - } - - public Event executeSearch(RequestContext context) { - // lookup the search criteria in "flow scope" - SearchCriteria criteria = - (SearchCriteria)context.getFlowScope().get("criteria"); - - // execute the search - Collection results = searchService.executeSearch(criteria); - - // set the results in "request scope" - context.getRequestScope().put("results", results); - - // return "success" - return success(); - } - - public Event someOtherRelatedActionMethod(RequestContext context) { - ... - return success(); - } - - public Event yetAnotherRelatedActionMethod(RequestContext context) { - ... - return success(); - } - } - - As you can see, this allows you to define one to many action methods per Action class. - With this approach, there are two requirements: - - - - Your Action class must extend from org.springframework.webflow.MultiAction, or - another class that extends from MultiAction. The multi action cares - for the action method dispatch that is based on the value of the method - property. - - - - - Each action method must conform to the signature illustrated above: public Event ${method}(RequestContext) { ... } - - - - - - MultiActions are useful for centralizing command logic on a per-flow definition basis, as - a flow definition typically carries out execution of a single application use case. - - - - ActionState API - multi action - - The following example constructs the equivalent action state definition using - the FlowBuilder API: - - - public class SearchFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - ... - addActionState("executeSearch", invoke("executeSearch", action("searchAction")), - transition(on("success"), to("displayResults"))); - ... - } - } - - - - ActionState XML - bean action - - The next example constructs an ActionState definition from XML that - executes a single method on a Plain Old Java Object (POJO) and then responds to the result: - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="executeSearch"/> - - <action-state id="executeSearch"> - <bean-action bean="searchService" method="executeSearch"> - <method-arguments> - <argument expression="${flowScope.criteria}"/> - </method-arguments> - <method-result name="results"/> - </bean-action> - <transition on="success" to="displayResults"/> - </action-state> - - ... - - </flow> - - This state definition reads "when the executeSearch - state is entered, call the executeSearch method on the - searchService passing it the object indexed by name criteria - in flowScope. On successful execution, expose the method - return value in the default scope (request) under the name results - and transition to the displayResults state." - - - In this example the referenced bean searchService would be - your application object, typically a transactional - business service. Such a service implementation must have defined the - the Collection executeSearch(SearchCriteria) method, - typically by implementing a service interface: - - - public interface SearchService { - public Collection executeSearch(SearchCriteria criteria); - } - - - With this approach there are no requirements on the signature of the methods that carry out - action execution, nor is there any requirement to extend from a Web Flow specific base class. - Basically, you are not required to write a custom Action implementation at all--you - simply instruct Spring Web Flow to call your business methods directly. The need - for custom "glue code" to bind your web-tier to your middle-tier is eliminated. - - - Spring Web Flow achieves this by automatically adapting the method on your existing - application object to the Action interface and caring for - exposing any return value in the correct scope. - - - This adaption process is shown graphically below: - - - - - - - - - - Bean->Action adapter - - - - - ActionState XML - decision bean action - - The following example constructs an ActionState from - XML that executes an action whose execution result forms the basis for the transition decision: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <action-state id="shippingRequired"> - <bean-action bean="shippingService" method="isShippingRequired"> - <method-arguments> - <argument expression="${flowScope.purchase}"/> - </method-arguments> - </bean-action> - <transition on="yes" to="enterShippingDetails"/> - <transition on="no" to="placeOrder"/> - </action-state> - - ... - - </flow> - - - This state definition reads "if the isShippingRequired method on the - shippingService returns true, transition to the enterShippingDetails - state, otherwise transition to the placeOrder state." - - - - Note how the boolean return value of the isShippingRequired method is - converted to the event identifiers yes or no. - - - - This conversion process is handled by the action adapter responsible for adapting the method on your - application object to the org.springframework.webflow.execution.Action interface. - By default, this adapter applies a number of rules for creating a result event from a method return value. - - - These conversion rules are: - - - Default method return value to Event conversion rules - - - - - - Return type - Event identifier - - - - - boolean - yes or no - - - java.lang.Enum - this.name() - - - org.springframework.core.enum.LabeledEnum - this.getLabel() - - - org.springframework.webflow.execution.Event - this.getId() - - - java.lang.String - the string - - - any other type - success - - - -
- - You may customize these default conversion policies by setting a custom ResultEventFactory - instance on the bean invoking action performing the adaption. Consult the JavaDoc documentation for - more details on how to do this. - -
- - ActionState XML - decision bean action with enum return value - - The following example constructs an ActionState from - XML that executes a action that invokes a method on an application object that - returns a java.lang.Enum: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <action-state id="shippingRequired"> - <bean-action bean="shippingService" method="calculateShippingMethod"/> - <method-arguments> - <argument expression="${flowScope.order}"/> - </method-arguments> - </bean-action> - <transition on="BASIC" to="enterBasicShippingDetails"/> - <transition on="EXPRESS" to="enterExpressShippingDetails"/> - <transition on="NONE" to="placeOrder"/> - </action-state> - - ... - - </flow> - - - This state definition reads "if the calculateShippingMethod method on the - shippingService returns BASIC for the current order, transition to the enterBasicShippingDetails - state. If the return value is EXPRESS, transition to the enterExpressShippingDetails state. - If the return value is NONE, transition to the placeOrder state." - - - - ActionState XML - evaluate action - - The following example constructs an ActionState from - XML that executes a action that evaluates an expression against the - flow request context and exposes the evaluation result: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - - <action-state id="getNextInterviewQuestion"> - <evaluate-action expression="flowScope.interview.nextQuestion()"/> - <evaluation-result name="question"/> - </evaluate-action> - <transition on="success" to="displayQuestion"/> - </action-state> - - </flow> - - - This state definition reads "evaluate the flowScope.interview.nextQuestion() expression, - and expose the result under name question in the default scope." - - - The expression can evaluate any object traversable from the flow's - org.springframework.webflow.execution.RequestContext. This example expression evaluates the - nextQuestion method on the interview - business object in flow scope. - - - - ActionState XML - set action - - The next example constructs an ActionState from - XML that executes an action on a success transition that sets an attribute in "flash scope": - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <view-state id="selectFile" view="fileUploadForm"> - <transition on="submit" to="uploadFile"/> - </view-state> - - <action-state id="uploadFile"> - <action bean="uploadAction" method="uploadFile"/> - <transition on="success" to="selectFile"> - <set attribute="fileUploaded" scope="flash" value="true"/> - </transition> - </action-state> - - </flow> - - - This flow definition reads "display the fileUploadForm. - On form submit, invoke the uploadFile method - on the uploadAction. On success, allow the user - to select another file to upload. Report that the last file was uploaded successfully by - setting the fileUploaded attribute in flash scope to - true. - - - - Flash scoped attributes are preserved until the next user event is signaled into - the flow execution. In this example, this means the fileUploaded - attribute is preserved across a redirect to the selectFile - view state and any subsequent browser refreshes. Only when the submit - event is signaled will the flash scope be cleared. - - - - - When to use which kind of action? - - Simple action, Multi action, bean action, evaluate action, set? When to use one or the other? - - - - Action implementation usage guidelines - - - - - - - Action type - Usage scenario - - - - - Simple (extends AbstractAction) - - You have a specialized behavior that stands on its own; - for creating lightweight stubs or mocks for testing purposes. - - - - MultiAction - - To group related command logic together. Particularly - useful for when there are multiple related behaviors - called by a flow. - - - - Bean action - - When the logical behavior maps well to a method call on a service - layer bean. When there is no "special" or exotic glue code - required. - - - - - EvaluateAction - - - When you need to invoke a bean in flow scope or evaluate - any other flow expression. - - - - - SetAction - - - When you need to set an attribute in flow or other scope - during the course of flow execution. - - - - -
-
-
- - DecisionState - - When entered, a decision state makes a flow routing decision. This process consists of: - - - - Evaluating one or more boolean expressions against the executing flow to decide - what state to transition to next. - - - - - - The properties of a org.springframework.webflow.engine.DecisionState are summarized below: - - - DecisionState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - transitions (inherited from TransitionableState) - - The transitions that are evaluated on an event occurrence that - forms the basis for the decision. - - - 1..* - - - - -
- - DecisionState XML - expression evaluation - - The following example constructs a DecisionState from - XML that evalutes a boolean expression to determine what transition - to execute: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - ... - - <decision-state id="shippingRequired"> - <if test="${flowScope.order.needsShipping}" then="enterShippingDetails" else="placeOrder"/> - </decision-state> - - ... - - </flow> - - - This state definition reads "if the needsShipping property on the - order object in flow scope is true, transition to the enterShippingDetails - state, otherwise transition to the placeOrder state." - - - - - Caution: flow definitions should not be vehicles for - business logic. In this case the decision made was controller logic, reasoning on a - pre-calculated value to decide what step of the flow to transition to next. That is the kind of logic that - should be in a flow definition. In contrast, having the state itself embed - the business rule defining how shipping status is calculated is a misuse. - Instead, push such a calculation into business application code where it belongs and instruct - the flow to invoke that code using an action. - - - - -
- - SubflowState - - When entered, a subflow state spawns another flow as a subflow. - - - Recall that a flow is a reusable, self-contained controller module. The ability for one flow to call another flow - gives you the ability to compose independent modules together to create complex controller workflows. Any flow can be used as subflow - by any other flow, and there is a well-defined contract in play. Specifically: - - - - - - A Flow is an instance of org.springframework.webflow.engine.Flow. - - - - - A newly launched flow can be passed input attributes, which it may choose - to map into its own local scope. - - - - - An ending flow can return output attributes. If the ended flow was launched as a subflow, - the resuming parent flow may choose to map these output attributes into its own scope. - - - - - - It is helpful to think of the process of calling a flow like calling a Java method. Flows can - be passed input arguments, and can produce return values just like methods can. Flows are more powerful because - they are potentially long-running, as they can span more than one request into the server. - - - The properties of a org.springframework.webflow.engine.SubflowState are summarized below: - - - SubflowState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - subflow - - The definition of the flow to be spawned as a subflow. - - - 1 - - - - - attributeMapper - - The strategy responsible for mapping input attributes to the subflow and - mapping output attributes from the subflow. - - - 0..* - - Null - - - -
- - When a SubflowState is entered, the following behavior occurs: - - - - The state first messages its attributeMapper, an instance of - org.springframework.webflow.engine.FlowAttributeMapper, - to prepare a Map of input attributes to pass to the subflow. - - - - - The subflow is spawned, passing the input attributes. When this happens, - the parent flow suspends itself in the subflow state until - the subflow ends. - - - - - When the subflow ends, a result event is returned describing the flow outcome - that occurred. The parent flow resumes back in the subflow state. - - - - - The resumed subflow state messages its attributeMapper to - map any output attributes returned by the subflow into flow scope, if necessary. - - - - - Finally, the resumed subflow state responds to the result event returned by the ended subflow - by matching and executing a state transition. - - - - - - The constructs used in spawning a flow as a subflow are shown graphically below: - - - - - - - - - - SubflowState class diagram - - - - SubflowState XML - with input attribute - - The following example constructs an SubflowState from - XML that spawns a shipping subflow: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <subflow-state id="enterShippingDetails" flow="shipping"> - <attribute-mapper> - <input-mapper> - <mapping source="flowScope.order.shipping" target="shipping"/> - </input-mapper> - </attribute-mapper> - <transition on="finish" to="placeOrder"/> - </subflow-state> - - ... - - </flow> - - - This subflow state definition reads "spawn the shipping flow, - passing it the value of the shipping property on the order - object in flow scope. When the shipping flow ends, respond to the finish - result event by transitioning to the placeOrder state." - - - - The inner structure and behavior of the shipping flow is fully encapsulated within - its own flow definition. A flow calling another flow as a subflow can pass that flow input - and capture its output, but it cannot see inside it. Flows are black boxes. - Because any flow can be used as a subflow, it can be reused in other contexts without change. - - - - - SubflowState API - input attributes - - The following illustrates the equivalent example using the FlowBuilder API: - - - public class OrderFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - ... - addSubflowState("enterShippingDetails", flow("shipping"), shippingMapper(), - transition(on("finish"), to("placeOrder"))); - ... - } - - protected FlowAttributeMapper shippingMapper() { - DefaultFlowAttributeMapper mapper = new DefaultFlowAttributeMapper(); - mapper.addInputMapping(mapping().source("flowScope.order.shipping").target("shipping").value()); - return mapper; - } - } - - - - Flow input mapping - input contract - - Within a flow definition, input attributes can be obtained by configuring an input-mapper. - Any input attributes must be explictly mapped. - The list of permitted input attributes defines the input contract for the flow. - - - If you think of calling a Flow as analogous to calling a Java method, it - is helpful to think of input-attributes as analogous to method arguments. - - - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <input-mapper> - <input-attribute name="shipping"/> - </input-mapper> - - ... - - </flow> - - - This short-form input mapper declaration reads "when a new execution of this flow starts, - map the provided shipping input attribute into flowScope under - the name shipping." - - - - Had this input mapping not been defined the shipping attribute made available as input - to this flow by a calling parent flow or external client would have been ignored. - - - -
- - EndState - - When entered, an end state terminates a flow. A EndState represents exactly one logical - flow outcome; for example, "finish", or "cancel". - - - If the ended flow was acting as a top-level or root flow, the - entire flow execution ends and cannot be resumed. In this case, the end state is responsible - for issuing a final response (for example, a confirmation page, or a redirect request to another flow or an external URL). - - - If the ended flow was acting as a subflow, the spawned subflow session ends and - the calling parent flow resumes by responding to the end - result returned. In this case, the responsibility for any final response - falls on the parent flow. - - - Once a flow ends, any attributes in flow scope go out of scope immediately - and become eligible for garbage collection. - - - As outlined, an end state entered as part of a root flow messages its finalResponseAction - to make a ending view selection. Typically this is a redirect-based response type, - allowing for redirect after flow completion. An end state entered as part of - a subflow is not responsible for a view selection; this responsibility falls on the calling flow. - - - EndState result events - - When a EndState is entered it terminates a flow and, if used as subflow, - returns a result event the parent flow uses to drive a state transition from the calling subflow - state. It is the end state's responsibility to create this result event which - is the basis for communicating the logical flow outcome to - callers. - - - By default, an EndState creates a result event with an identifier that matches the - identifier of the end-state itself. For example, an end state with id finish - returns a result event with id finish. Also, any attributes in - flow scope that have been explicitly mapped as output attributes - are returned as result event attributes. This allows you to return data along - with the logical flow outcome. - - - Spring Web Flow gives you full control over the ending view selection strategy, as - well as what flow attributes should be exposed as output on a per EndState basis. - These configurable properties are summarized below: - - - - EndState Properties - - EndState properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - finalResponseAction - The strategy that makes the ending response when this state is entered and the flow is a root flow. - - 0..1 - - Null - - - outputMapper - - The service responsible for exposing flow output attributes, making those attributes eligible for output mapping by a calling flow. - - - 0..1 - - None - - - -
-
- - EndState XML - redirect to flow after completion - - The following example constructs an EndState from - XML that terminates a shipping subflow and requests a - redirect response to another flow: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <end-state id="finish" view="flowRedirect:searchFlow"/> - - </flow> - - - This end state definition reads "terminate the order flow, - and redirect to a new execution of the searchFlow". - - - - EndState XML - redirect after flow completion - - The following example constructs an EndState from - XML that terminates a shipping subflow and requests a - redirect response to an external URL: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <end-state id="finish" view="externalRedirect:/orders/${flowScope.order.id}"/> - - </flow> - - - This end state definition reads "terminate the order flow, - and redirect to the URL returned by evaluating the /orders/${flowScope.order.id} - expression." - - - This is an example of the familiar redirect after post pattern where - after transaction completion a redirect is issued allowing the result of the transaction - to be viewed (in this case using a REST-style URL). - - - - EndState XML - flow output attribute - - The following example constructs an EndState from - XML that terminates a shipping subflow: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <end-state id="finish"> - <output-mapper> - <output-attribute name="shipping"/> - </output-mapper> - </end-state> - - </flow> - - - This end state definition reads "terminate the shipping flow, - and expose the shipping property in flow scope as an output attribute - with name shipping." - - - - EndState API - flow output attribute - - The following illustrates the equivalent example using the FlowBuilder API: - - - public class ShippingFlowBuilder extends AbstractFlowBuilder { - public void buildStates() { - ... - addEndState("finish", - new DefaultAttributeMapper().add( - mapping().source("flowScope.shipping").target("shipping").value() - ); - } - } - - - Since this end-state does not make a view selection, it is expected this flow will be always used - as a subflow. When this flow ends, the calling parent flow is expected to respond to the - finish result, and may choose to map the shipping output - attribute into its own scope. - - - - SubflowState XML - mapping an output attribute - - The next example shows how a subflow-state can respond to the ending - result of a subflow, and map subflow output attributes into its own scope: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - ... - - <subflow-state id="enterShippingDetails" flow="shipping"> - <attribute-mapper> - <output-mapper> - <output-attribute name="shipping"/> - </output-mapper> - </attribute-mapper> - <transition on="finish" to="placeOrder"/> - </subflow-state> - - ... - - </flow> - - - This subflow state definition reads "spawn the shipping flow - as a subflow. When the shipping flow ends, map the shipping output - attribute into flow scope under the name shipping, then respond to - the finish result event by transitioning to - the placeOrder state." - - - - Had this output mapping not been defined, the shipping attribute made available as output - to this flow by the ending subflow would have been ignored. - - - -
-
-
\ No newline at end of file diff --git a/spring-webflow/docs/reference/src/flow-execution-repository.xml b/spring-webflow/docs/reference/src/flow-execution-repository.xml deleted file mode 100644 index b6009062..00000000 --- a/spring-webflow/docs/reference/src/flow-execution-repository.xml +++ /dev/null @@ -1,247 +0,0 @@ - - - Flow execution repositories - - Introduction - - A flow execution represents an executing flow at a point in time. - At runtime there can be any number of flow executions active in parallel. A single user - can even have multiple executions active at the same time (for example, when a user is - operating multiple windows or tabs within their browser). - - - Many of these flow executions span multiple requests into the server and therefore - must be saved so they can be resumed on subsequent requests. This presents technical - challenges, as there must exist a stable mechanism for a new request to be associated - with an existing execution in the view state that matches what the user expects. This problem - is more difficult when you consider that many applications require use of browser - navigational buttons, and use of these buttons involves updating local history without - notifying the server. - - - The problem of flow execution persistence is addressed by Spring Web Flow's flow - execution repository subsystem. In this chapter, you will learn how to use the system - to manage the storage of active web conversations in a stable manner. - - - - Repository architecture overview - - Recall the following bullet points noting what happens when a flow execution enters a ViewState: - - - - - - When a flow execution reaches a ViewState it is said to have paused, - where it waits in that state for user input to be provided so it can continue. After pausing, the - ViewSelection returned is used to issue a response to the user - that provides a vehicle for collecting the required user input. - - - - - User input is provided by signaling an event that - resumes the flow execution in the paused view state. - The input event communicates what user action was taken. - - - - - - Each time an active flow execution is paused, it is saved out to a - repository. When the next request comes in for that flow execution, it is restored - from the repository, resumed, and continued. This process continues - until the flow execution reaches an end state, at which time it is removed from the repository. - - - This process is demonstrated over the next two graphics: - - - - - - - - - - Request one (1) - Paused flow execution persistence - - - - - - - - - - - Request two (2) - Paused flow execution restoration, removal on end - - - - - Flow execution identity - - When a new flow execution is created, it marks the start of a new conversation between a browser - and the server. A new flow execution that is still active after startup - processing indicates the start of a conversation that will span more than one request - and needs to be persisted. When this is the case, that flow execution is assigned - an persistent identifer by the repository. By default, the - structure of this identifier consists of a two-part composite key. This key is used - by clients to restore the flow execution on subsequent requests. - - - Conversation identifier - - The first part of a flow execution's persistent identity is a - unique conversation identifier. This serves as an index into - the logical conversation between the browser and the server that - has just started. - - - - Continuation identifier - - The second part of a flow execution's persistent identity is a continuation identifier. - This identifier serves as an index into a flow execution representing the state of the conversation - at this point in time. - - - - Flow execution key - - Together the conversation id plus the continuation id make up the unique two-part - flow execution key that identifies a state - of a conversation at a point in time. By submitting this key - in a subsequent request, a browser can restore the conversation at that point - and continue from there. - - - So on a subsequent request, the conversation is resumed by restoring a flow execution - from the repository using the two-part key. After event processing, if the - flow execution is still active it is saved back out to the repository. - At this time a new flow execution key is generated. By default, that key - retains the same conversation identifier, as the same logical - conversation is in progress; however the continuation identifier - changes to provide an index into the state of the flow execution - at this new point in time. - - - By submitting this new key in a subsequent request, a browser can - restore the conversation at that point and continue from there. - This process continues until a flow execution reaches an end state during event processing - signaling the end of the conversation. - - - - - Conversation ending - - When a flow execution reaches an end state it terminates. If the flow execution was associated - with a logical conversation that spanned more than on request, it is removed from the - repository. More specifically, the entire conversation is ended, - resulting in any flow execution continuations associated with the conversation being purged. - - - Once a conversation has ended, the conversation identifier is no longer valid - and can never be used again. - - - - Flow execution repository implementations - - The next section looks at the repository implementations that are available for use - with Spring Web Flow out-of-the-box. - - - Simple flow execution repository - - The simplest possible repository (SimpleFlowExecutionRepository). - This repository stores exactly one flow execution instance per conversation - in the user's session, invalidating it when its end state is reached. - This repository implementation has been designed with minimal storage overhead in mind. - - - - It is important to understand that use of this repository consistently prevents - duplicate submission when using the back button. If you attempt to go back - and resubmit, the continuation id stored in your browser history will not - match the current continuation id needed to access the flow execution and - access will be disallowed. - - - - - This repository implementation should generally be used when you do not have to - support browser navigational button use; for example, when you lock down the browser and - require that all navigation events to be routed through Spring Web Flow. - - - - - Continuation flow execution repository - - This repository (ContinuationFlowExecutionRepository) stores one to many flow - execution instances per conversation in the user's session, where each flow execution represents a - paused and restorable state of the conversation at a point in time. This repository implementation is - considerably more flexible than the simple one, but incurs more storage overhead. - - - - It is important to understand that use of this repository allows resubmission when - using the back button. If you attempt to go back and resubmit while the conversation - is active, the continuation id stored in your browser history will match the - continuation id of a previous flow execution in the repository. Access to - that flow execution representing the state of the conversation at that point in - time will be granted. - - - - Like the simple implementation, this repository implementation provides support for conversation - invalidation after completion where once a logical - conversation completes (by one of its FlowExecutions reaching an end state), - the entire conversation is invalidated. This prevents the possibility of - resubmission after completion. - - - This repository is more elaborate than the default repository, offering - more power (by enabling multiple continuations to exist per conversation), - but incurring more storage overhead. This repository implementation should be - considered when you do have to support browser navigational button use. - This implementation is the default. - - - - Client continuation flow execution repository - - This repository is entirely stateless and its use entails no server-side state - (ClientContinuationFlowExecutionRepository). - - - This is achieved by encoding a serialized flow execution directly into the - flow execution continuation key that is sent in the response. - - - When asked to load a flow execution by its key on a subsequent request, this - repository decodes and deserializes the flow execution, restoring it to - the state it was in when it was serialized. - - - - This repository implementation does not currently support - conversation invalidation after completion, as - this capability requires tracking active conversations using some - form of centralized storage, like a database table. - - - - - Storing state (a flow execution continuation) on the client - entails a certain security risk that should be evaluated. Furthermore, it - puts practical constraints on the size of the flow execution. - - - - - \ No newline at end of file diff --git a/spring-webflow/docs/reference/src/flow-execution.xml b/spring-webflow/docs/reference/src/flow-execution.xml deleted file mode 100644 index 8f7176e7..00000000 --- a/spring-webflow/docs/reference/src/flow-execution.xml +++ /dev/null @@ -1,673 +0,0 @@ - - - Flow execution - - Introduction - - Once a flow has been defined, any number of executions of it can be launched in parallel - at runtime. Execution of a flow is carried out by a dedicated system that - is based internally on a state machine that runs atop the Java VM. As the life of a - flow execution can span more than one request into the server, this system - is also responsible for persisting execution state across requests. - - - This chapter documents Spring Web Flow's flow execution system. You will - learn the core constructs of the system and how to execute flows out-of-container - within a JUnit test environment. - - - - FlowExecution - - A org.springframework.webflow.execution.FlowExecution is a runtime instantiation of a flow definition. - Given a single FlowDefinition, any - number of independent flow executions may be created. - These executions are typically created by a FlowExecutionFactory. - - - A flow execution carries out the execution of program instructions defined within - its definition in response to user events. - - - - It may be helpful to think of a flow definition as analagous to a Java Class, and a - flow execution as analagous to an object instance of that Class. Signaling - an execution event can be considered analagous to sending an object a message. - - - - Flow execution creation - - FlowDefinition definition = ... - FlowExecutionFactory factory = ... - FlowExecution execution = factory.createFlowExecution(definition); - - - Once created, a new flow execution is initially inactive, waiting to be started. Once - started, a flow execution becomes active by entering its startState. - From there, it continues executing until it enters a state where user input is required - to continue or it terminates. - - - - Flow execution startup - - ExternalContext context = ... - execution.start(context); - - - When a flow execution reaches a state where input is required to continue, it is said to have paused, - where it waits in that state for user input to be provided. - - - User input is provided by signaling an event that - resumes the flow execution by communicating what user action was taken. - Attributes of the signal event request form the basis for user input. The flow execution - resumes by consuming the event. - - - Once a flow execution has resumed, it continues executing until it again enters a - state where more input is needed or it terminates. Once a flow execution has terminated - it becomes inactive and cannot be resumed. - - - - Flow execution resume - - ExternalContext context = ... - execution.resume(context); - if (execution.isActive()) { - // still active but paused - } else { - // has ended - } - - - - Flow execution lifecycle - - As outlined, a flow execution can go through a number of phases throughout its lifecycle; - for example, created, active, paused, - ended. - - - Spring Web Flow gives you the ability to observe the lifecycle of an - executing flow by implementing a FlowExecutionListener. - - - The different phases of a flow execution are shown graphically below: - - - - - - - - - - Flow execution lifecycle - - - - - Flow execution properties - - The Spring Web Flow flow execution implementation is org.springframework.webflow.engine.impl.FlowExecutionImpl, - typically created by a FlowExecutionImplFactory (a FlowExecutionFactory implementation). - The configurable properties of this flow execution implementation are summarized below: - - - Flow Execution properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - definition - The flow definition to be executed. - - 1 - - - - listeners - The set of observers observing the lifecycle of this flow execution. - - 0..* - - Empty - - - attributes - Global system attributes that can be used to affect flow execution behavior - - 0..* - - Empty - - - -
- - The configurable constructs related to flow execution are shown graphically below: - - - - - - - - - - Flow execution - - -
- - Flow execution impl creation - - FlowExecutionFactory factory = new FlowExecutionImplFactory(); - factory.setExecutionListeners(...); - factory.setExecutionAttributes(...); - FlowExecution execution = factory.createFlowExecution(definition); - - -
- - Flow execution context - - Once created, a flow execution, representing the state of a flow at a point in time, - maintains contextual state about itself that can be reasoned upon by clients. In addition, - a flow execution exposes several data structures, called scopes, that allow clients to set - arbitrary attributes that are managed by the execution. - - - The contextual properties associated with a flow execution are summarized below: - - - Flow Execution Context properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - active - - A flag indicating if the flow execution is active. - An inactive flow execution has either ended or has never been started. - - - 1 - - - - definition - - The definition of the flow execution. The flow definition serves as - the blueprint for the program. It may be helpful to think of a flow - definition as like a Class and a - flow execution as like an instance of that Class. - This method may always be safely called. - - - 1 - - - - activeSession - - The active flow session, tracking the flow that is currently executing - and what state it is in. The active session can change over the life of the - flow execution because a flow can spawn another flow as a subflow. - This property can only be queried while the flow execution is active. - - - 1 - - - - conversationScope - - A data map that forms the basis for "conversation scope". Arbitrary attributes placed in this map will be retained - for the life of the flow execution and correspond to the length of the logical conversation. - This map is shared by all flow sessions. - - - 1 - - - - -
- - As a flow execution is manipulated by clients its contextual state changes. Consider how - contextual state is effected when the following events occur: - - - An ordered set of events and their effects on flow execution context - - - - - - - Flow Execution Event - Active? - Value of the activeSession property - - - - - created - false - Throws an IllegalStateException - - - started - true - - A FlowSession whose definition - is the top-level flow definition and whose state is the definition's start state. - - - - state entered - true - - A FlowSession whose definition - is the top-level flow definition and whose state is the newly entered state. - - - - subflow spawned - true - - A FlowSession whose definition - is the subflow definition and whose state is the subflow's start state. - - - - subflow ended - true - - A FlowSession whose definition is back to the - top-level flow definition and whose state is the resuming state. - - - - ended - false - Throws an IllegalStateException - - - -
- - As you can see, the activeSession of a flow execution changes when a subflow - is spawned. Each flow execution maintains a stack of flow sessions, where each flow session - represents a spawned instance of a flow definition. When a flow execution starts, the session stack initially - consists of one (1) entry, an instance dubbed the root session. - When a subflow is spawned, the stack increases to two (2) entries. When the subflow ends, - the stack decreases back to one (1) entry. The active session is always - the session at the top of the stack. - - - The contextual properties associated with a FlowSession are summarized below: - - - Flow Session properties - - - - - - - - Property name - Description - Cardinality - Default value - - - - - definition - - The definition of the flow the session is an instance of. - - - 1 - - - - state - - The current state of the session. - - - 1 - - - - status - - A status indicator describing what the session is currently doing. - - - 1 - - - - scope - - A data map that forms the basis for flow scope. - Arbitrary attributes placed in this map will be retained for the scope - of the flow session. This map is local to the session. - - - 1 - - - - flashMap - - A data map that forms the basis for flash scope. - Attributes placed in this map will be retained until the next - external user event is signaled in the session. - - - 1 - - - - -
- - The following graphic illustrates an example flow execution context and flow - session stack: - - - - - - - - - - Flow execution context - - - - In this illustration, a flow execution has been created for the Book Flight flow. - The execution is currently active and the activeSession indicates it - is in the Display Seating Chart state of the Assign Seats flow, - which was spawned as a subflow from the Enter Seat Assignments state. - - - - Note how the active session status is paused, indicating the flow execution - is currently waiting for user input to be provided to continue. In this case, it is - expected the user will choose a seat for their flight. - - -
- - Flow execution scopes - - As alluded to, a flow execution manages several containers called scopes, - which allow arbitrary attributes to be stored for a period of time. There are four scope - types, each with different storage management semantics: - - - Flow execution scope types - - - - - - Scope type name - Management Semantics - - - - - request - - Eligible for garbage collection when a single call into the flow execution completes. - - - - flash - - Cleared when the next user event is signaled into the flow session; eligible for garbage collection when the flow session ends. - - - - flow - - Eligible for garbage collection when the flow session ends. - - - - conversation - - Eligible for garbage collection when the root session of the governing flow execution (logical conversation) ends. - - - - -
-
- - Flow execution testing - - Spring Web Flow provides support within the org.springframework.webflow.test - package for testing flow executions with JUnit. This support is provided as convenience but is - entirely optional, as a flow execution is instantiable in any environment with the standard - Java new operator. - - - The general strategy for testing flows follows: - - - - - - Your own implementations of definitional artifacts used by a flow such as actions, - attribute mappers, and exception handlers should be unit tested in isolation. - Spring Web Flow ships convenient stubs to assist with this, for instance - MockRequestContext. - - - - - The execution of a flow should be tested as part of a system integration test. - Such a test should exercise all possible paths of the flow, asserting that - the flow responds to events as expected. - - - - - - - A flow execution integration test typically selects mock or stub implementations of application - services called by the flow, though it may also exercise production implementations. - Both are useful, supported system test configurations. - - - - Flow execution test example - - To help illustrate testing a flow execution, first consider the following flow definition - to search a phonebook for contacts: - - - - - - - - - - Phonebook Search Flow - State Diagram - - - - The corresponding XML-based flow definition implementation: - - - <?xml version="1.0" encoding="UTF-8"?> - <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"> - - <start-state idref="enterCriteria"/> - - <view-state id="enterCriteria" view="searchCriteria"> - <render-actions> - <action bean="formAction" method="setupForm"/> - </render-actions> - <transition on="search" to="displayResults"> - <action bean="formAction" method="bindAndValidate"/> - </transition> - </view-state> - - <view-state id="displayResults" view="searchResults"> - <render-actions> - <bean-action bean="phonebook" method="search"> - <method-arguments> - <argument expression="flowScope.searchCriteria"/> - </method-arguments> - <method-result name="results"/> - </bean-action> - </render-actions> - <transition on="newSearch" to="enterCriteria"/> - <transition on="select" to="browseDetails"/> - </view-state> - - <subflow-state id="browseDetails" flow="detail-flow"> - <attribute-mapper> - <input-mapper> - <mapping source="requestParameters.id" target="id" from="string" to="long"/> - </input-mapper> - </attribute-mapper> - <transition on="finish" to="displayResults"/> - </subflow-state> - - </flow> - - - Above you see a flow with three (3) states that execute these behaviors, respectively: - - - - - - The first state enterCriteria displays a search criteria form so the user can enter who - he or she wishes to search for. - - - - - On form submit and successful data binding and validation, the search is executed. - After search execution a results view is displayed. - - - - - From the results view, the user may select a result they wish to browse additional details on - or they may request a new search. On select, the "detail" flow is spawned and - when it finishes the search is re-executed and it's results redisplayed. - - - - - - From this behavior narrative the following assertable test scenarios can be extracted: - - - - - That when a flow execution starts, it enters the enterCriteria state and - makes a searchCriteria view selection containing a form object - to be used as the basis for form field population. - - - - - That on submit with valid input, the search is executed and a searchResults view selection is made. - - - - - That on submit with invalid input, the searchCriteria view is reselected. - - - - - That on newSearch, the searchCriteria view is selected. - - - - - That on select, the detail flow is spawned and passed the id of the selected result as expected. - - - - - To assist with writing these assertions, Spring Web Flow ships with JUnit-based flow execution - test support within the org.springframwork.webflow.test package. - These base test classes are indicated below: - - - Flow execution test support hierarchy - - - - - - Class name - Description - - - - - AbstractFlowExecutionTests - The most generic base class for flow execution tests. - - - AbstractExternalizedFlowExecutionTests - The base class for flow execution tests whose flow is defined within an externalized resource, such as a file. - - - AbstractXmlFlowExecutionTests - The base class for flow execution tests whose flow is defined within an externalized XML resource. - - - -
-
-
-
\ No newline at end of file diff --git a/spring-webflow/docs/reference/src/flow-executor.xml b/spring-webflow/docs/reference/src/flow-executor.xml deleted file mode 100644 index 8ebd1ed8..00000000 --- a/spring-webflow/docs/reference/src/flow-executor.xml +++ /dev/null @@ -1,230 +0,0 @@ - - - Flow executors - - Introduction - - Flow executors are the highest-level entry points into - the Spring Web Flow system, responsible for driving the execution of flows - across a variety of environments. - - - In this chapter, you will learn how to execute flows within Spring MVC, Struts, - and Java Server Faces (JSF) based applications. - - - - FlowExecutor - - org.springframework.webflow.executor.FlowExecutor is the - central facade interface external systems use to drive the execution of flows. - This facade acts as a simple, convenient service entry-point into - the Spring Web Flow system that is reusable across environments. - - - The FlowExecutor interface is shown below: - - - public interface FlowExecutor { - public void executeFlowRequest(ExternalContext context); - } - - - Execution typically consists of either: - - - - Launching (start) a new execution of a flow definition. - - - - - Resuming a paused flow execution by signaling an event against its current state. - - - - - - The ExternalContext provides normalized access to properties of an external system that has called into Spring Web Flow. - This context allows access to environment-specific request parameters as well as - externally-managed request, session, and application-level attributes. - - - ExternalContext implementations exist for each of - the environments Spring Web Flow supports. If a flow artifact such as an Action needs - to access native constructs of the calling environment it can downcast a context to its - specific implementation. The need for such downcasting is considered a corner case. - - - FlowExecutorImpl - - The default executor implementation is org.springframework.webflow.executor.FlowExecutorImpl. - It allows for configuration of a FlowDefinitionLocator responsible for loading the flow definitions to execute, as well as - the FlowExecutionRepository strategy responsible for persisting flow executions that remain - active beyond a single request into the server. - - - The configurable FlowExecutorImpl properties are shown below: - - - FlowExecutorImpl properties - - - - - - - Property name - Description - Cardinality - - - - - definitionLocator - The service for loading flow definitions to be executed, typically a FlowDefinitionRegistry - - 1 - - - - executionFactory - The factory for creating new flow executions. - - 1 - - - - executionRepository - The repository for saving and loading persistent (paused) flow executions - - 1 - - - - -
-
- - A typical flow executor configuration with Spring 2.0 - - <?xml version="1.0" encoding="UTF-8"?> - <beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:web="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-2.0.xsd"> - - <!-- Launches new flow executions and resumes existing executions. --> - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry"/> - - <!-- Creates the registry of flow definitions for this application --> - <web:flow-registry id="flowRegistry"> - <web:flow-location path="/WEB-INF/flows/**/*-flow.xml"/> - </web:flow-registry> - - </beans> - - - This instructs Spring to create a flow executor that can execute all XML-based flow definitions - contained within the /WEB-INF/flows directory. The default flow execution - repository, continuation, is used. - - - - A flow executor using a simple execution repository - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="simple"/> - - - This executor is configured with a simple repository that manages - execution state in the user session. - - - - A flow executor using a client-side continuation-based execution repository - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="client"/> - - - This executor is configured with a continuation-based repository that serializes - continuation state to the client using no server-side state. - - - - A flow executor using a single key execution repository - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="singleKey"/>> - - - This executor is configured with a simple repository that assigns a single - flow execution key per conversation. The key, once assigned, never changes - for the duration of the conversation. - - - - A flow executor setting custom conversation management attributes - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry"> - <web:flow-repository type="continuation" max-conversations="5" max-continuations="30" conversation-manager-ref="conversationManager"/> - </web:flow-executor> - - <bean id="conversationManager" class="example.MyCustomConversationalStateManager"/> - - - This executor is configured with a continuation repository configured with custom settings for: - - The maximum number of active conversations per user session (5) - The maximum number of restorable flow execution snapshots (continuations) per conversation (30) - Where conversational state will be stored (via a custom conversationManager) - - The flow:repository child element is the more flexible form for configuring the flow execution repository. - Use it or the convenient repository-type attribute, not both. - - - - A flow executor setting system execution attributes - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"> - <web:flow-execution-attributes> - <web:alwaysRedirectOnPause value="false"/> - <web:attribute name="foo" value="bar"/> - </flow:execution-attributes> - </web:flow-executor> - - - This executor is configured to set two flow execution system attributes - alwaysRedirectOnPause=false and foo=bar. - - - - - The alwaysRedirectOnPause attribute determines if - a flow execution redirect occurs automatically each time an execution pauses - (automated POST+REDIRECT+GET behavior). - Setting this attribute to false will disable the default 'true' behavior. - - - - - - A flow executor setting custom execution listeners - - <web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"> - <web:flow-execution-listeners> - <web:flow-listener ref="listener" criteria="order-flow"/> - </web:flow-execution-listeners> - </web:flow-executor> - - <!-- A FlowExecutionListener to observe the lifecycle of order-flow executions --> - <bean id="listener" class="example.OrderFlowExecutionListener"/> - - - This executor is configured to apply the execution listener to the "order-flow". - - -
-
\ No newline at end of file diff --git a/spring-webflow/docs/reference/src/images/actionadapter-classdiagram.png b/spring-webflow/docs/reference/src/images/actionadapter-classdiagram.png deleted file mode 100644 index f09de8c8..00000000 Binary files a/spring-webflow/docs/reference/src/images/actionadapter-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/actionstate-classdiagram.jpg b/spring-webflow/docs/reference/src/images/actionstate-classdiagram.jpg deleted file mode 100644 index f6a6a7c2..00000000 Binary files a/spring-webflow/docs/reference/src/images/actionstate-classdiagram.jpg and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/architecture-layer-diagram.png b/spring-webflow/docs/reference/src/images/architecture-layer-diagram.png deleted file mode 100644 index c8d707ef..00000000 Binary files a/spring-webflow/docs/reference/src/images/architecture-layer-diagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flow-search.png b/spring-webflow/docs/reference/src/images/flow-search.png deleted file mode 100644 index 2faaa307..00000000 Binary files a/spring-webflow/docs/reference/src/images/flow-search.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowdefinition-classdiagram.png b/spring-webflow/docs/reference/src/images/flowdefinition-classdiagram.png deleted file mode 100644 index 911629fd..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowdefinition-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecution-classdiagram.png b/spring-webflow/docs/reference/src/images/flowexecution-classdiagram.png deleted file mode 100644 index af3fd181..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecution-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecution-persistence.png b/spring-webflow/docs/reference/src/images/flowexecution-persistence.png deleted file mode 100644 index 69addc6f..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecution-persistence.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecution-restoration.png b/spring-webflow/docs/reference/src/images/flowexecution-restoration.png deleted file mode 100644 index 0b8ad8a5..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecution-restoration.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecution-sessionstack.png b/spring-webflow/docs/reference/src/images/flowexecution-sessionstack.png deleted file mode 100644 index 3b258ef8..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecution-sessionstack.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecution-statediagram.png b/spring-webflow/docs/reference/src/images/flowexecution-statediagram.png deleted file mode 100644 index 766cab0e..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecution-statediagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/flowexecutorfacade-classdiagram.png b/spring-webflow/docs/reference/src/images/flowexecutorfacade-classdiagram.png deleted file mode 100644 index 961d9ece..00000000 Binary files a/spring-webflow/docs/reference/src/images/flowexecutorfacade-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/globaltransitions-statediagram.png b/spring-webflow/docs/reference/src/images/globaltransitions-statediagram.png deleted file mode 100644 index 60820668..00000000 Binary files a/spring-webflow/docs/reference/src/images/globaltransitions-statediagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/hotels-site-bookhotel-flow.png b/spring-webflow/docs/reference/src/images/hotels-site-bookhotel-flow.png new file mode 100644 index 00000000..fe8a2f9b Binary files /dev/null and b/spring-webflow/docs/reference/src/images/hotels-site-bookhotel-flow.png differ diff --git a/spring-webflow/docs/reference/src/images/hotels-site.png b/spring-webflow/docs/reference/src/images/hotels-site.png new file mode 100644 index 00000000..529f7372 Binary files /dev/null and b/spring-webflow/docs/reference/src/images/hotels-site.png differ diff --git a/spring-webflow/docs/reference/src/images/junit-greenbar.png b/spring-webflow/docs/reference/src/images/junit-greenbar.png deleted file mode 100644 index 04d2f6b1..00000000 Binary files a/spring-webflow/docs/reference/src/images/junit-greenbar.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/logo-ervacon.png b/spring-webflow/docs/reference/src/images/logo-ervacon.png deleted file mode 100644 index 62b3b1e8..00000000 Binary files a/spring-webflow/docs/reference/src/images/logo-ervacon.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/logo-interface21.png b/spring-webflow/docs/reference/src/images/logo-interface21.png deleted file mode 100644 index 81889731..00000000 Binary files a/spring-webflow/docs/reference/src/images/logo-interface21.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/sellitem-configuration.png b/spring-webflow/docs/reference/src/images/sellitem-configuration.png deleted file mode 100644 index cb420480..00000000 Binary files a/spring-webflow/docs/reference/src/images/sellitem-configuration.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/subflowstate-classdiagram.png b/spring-webflow/docs/reference/src/images/subflowstate-classdiagram.png deleted file mode 100644 index 59e3c466..00000000 Binary files a/spring-webflow/docs/reference/src/images/subflowstate-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/swf-highlevelarchitecture.png b/spring-webflow/docs/reference/src/images/swf-highlevelarchitecture.png deleted file mode 100644 index 8f47196e..00000000 Binary files a/spring-webflow/docs/reference/src/images/swf-highlevelarchitecture.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/transition-statediagram.jpg b/spring-webflow/docs/reference/src/images/transition-statediagram.jpg deleted file mode 100644 index 38c9278f..00000000 Binary files a/spring-webflow/docs/reference/src/images/transition-statediagram.jpg and /dev/null differ diff --git a/spring-webflow/docs/reference/src/images/viewstate-classdiagram.png b/spring-webflow/docs/reference/src/images/viewstate-classdiagram.png deleted file mode 100644 index af7fe301..00000000 Binary files a/spring-webflow/docs/reference/src/images/viewstate-classdiagram.png and /dev/null differ diff --git a/spring-webflow/docs/reference/src/index.xml b/spring-webflow/docs/reference/src/index.xml index fa242452..9ea2038d 100644 --- a/spring-webflow/docs/reference/src/index.xml +++ b/spring-webflow/docs/reference/src/index.xml @@ -3,20 +3,14 @@ "../lib/docbook-dtd/docbookx.dtd" [ - - - - - - + ]> - Spring Web Flow Reference Documentation - Version 2.0-m4 + Version 2.0 M4 March 2008 @@ -54,11 +48,6 @@ &overview; - &flow-definition; - &flow-execution; - &flow-execution-repository; - &flow-executor; - &spring-faces; - &practical; + &defining-flows; \ No newline at end of file diff --git a/spring-webflow/docs/reference/src/overview.xml b/spring-webflow/docs/reference/src/overview.xml index 3eebcc31..f696003c 100644 --- a/spring-webflow/docs/reference/src/overview.xml +++ b/spring-webflow/docs/reference/src/overview.xml @@ -2,630 +2,50 @@ Preface - Many web applications consist of a mix of free browsing, - where the user is allowed to navigate a web site as they please, - and controlled navigations where the user is guided through - a series of steps towards completion of a business goal. - - - Consider the typical shopping cart application. While a user is - shopping, she is freely browsing available products, adding her - favorites to her cart while skipping over others. This is a good - "free browsing" use case. However, when the user decides to - checkout, a controlled workflow begins--the checkout process. - Such a process represents a single user conversation that takes - place over a series of steps, and navigation from step-to-step - is controlled. The entire process represents an discrete - application transaction that must complete exactly once - or not at all. + Many web applications require the same sequence of steps to execute in different contexts. + Often these sequences are merely components of a larger task the user is trying to accomplish. + Such a reusable sequence is called a flow. - Consider some other good examples of "controlled navigations": - applying for a loan, paying your taxes on-line, - booking a trip reservation, registering an account, or - updating a warehouse inventory. + Consider a typical shopping cart application. + User registration, login, and cart checkout are all examples of flows that can be invoked from several places in this type of application. - Traditional approaches to modeling and enforcing such controlled - navigations or "flows" fall flat, and fail to express the Flow as a - first class concept. Spring Web Flow (SWF) is a component of the - Spring Framework's web stack focused on solving this problem - in a productive and powerful manner. + Spring Web Flow (SWF) is the module of Spring that focuses on being the definitive solution for implementing flows. + The Web Flow engine plugs into the Spring Web MVC platform and provides declarative flow definition language. + This reference guide shows you how to use and extend Spring Web Flow. Introduction - - Overview + + What this guide covers - Spring Web Flow (SWF) is a component of the - Spring Framework's web stack focused on the - definition and execution of UI flow within - a web application. - - - The system allows you to capture a logical flow - of your web application as a self-contained module - that can be reused in different situations. Such - a flow guides a single user through the implementation - of a business task, and represents a single user - conversation. - Flows often execute across HTTP requests, - have state, exhibit transactional characteristics, - and may be dynamic and/or long-running in nature. - - - Spring Web Flow exists at a higher level of abstraction, integrating - as a self-contained flow engine within - base frameworks such as Struts, Spring MVC, Portlet MVC, and JSF. - SWF provides you the capability to capture your - application's UI flow explicitly in a declarative, - portable, and manageable fashion. SWF is - a powerful controller framework based on a finite-state machine, - fully addressing the "C" in MVC. + This guide covers all aspects of Spring Web Flow. + It is organized into two major sections, a Users Section followed by an Architects Section. + The Users Section covers implementing flows in end-user applications and working with the feature set. + The Architects Section covers extending the framework and the overall architectural model. - - Architecture overview + + What Web Flow requires to run - Spring Web Flow has been architected as a self-contained flow engine - with few required dependencies on third-party APIs. All dependencies are - carefully managed. + Java 1.4 or higher - At a minimum, to use Spring Web Flow you need: - - - - spring-webflow (the framework) - - - spring-core (miscellaneous utility classes used internally by the framework) - - - spring-binding (the Spring data binding framework, used internally) - - - commons-logging (a simple logging facade, used internally) - - - OGNL (the default expression language) - - - - Most users will embed SWF as a component within a larger web application development - framework, as SWF is a focused controller technology that expects a - calling system to care for request mapping and response rendering. In this case, those users - will depend on a thin integration piece for their environment. For example, those executing - flows within a Servlet environment might use the Spring MVC integration to care for dispatching - requests to SWF and rendering responses for SWF view selections. Spring Web Flow ships - convenient Spring MVC, Struts Classic, and JSF integration out of the box. - - - - - Spring Web Flow, like Spring, is a layered framework, - packaged in a manner that allows teams to use the parts they need and nothing else. - For example, one team might use Spring Web Flow in a Servlet environment with Spring MVC - and thus require the Spring MVC integration. Another team might use SWF in a Portlet - environment, and thus require the Portlet MVC integration. Another team might mix and match. - A major benefit of SWF is that it allows you to define reusable, self-contained controller - modules that can execute in any environment. - - + Spring 2.5.2 or higher - - Architectural layers + + Where to get additional support - Spring Web Flow is a layered framework. A diagram of Spring Web Flow's layered architecture is - shown below: - - - - - - - - - - Spring Web Flow layer diagram - - - - - Layer descriptions - - Each layer is partitioned into one or more subsystems that together - carry out the layer's role within the overall system. This section notes - the purpose of each layer and describes each subsystem in the following format: - - - - - Subsystem name - The name of a layer subsystem. - - - - - Description - The purpose of the subsystem. - - - - - Packages - The Java packages that contain the source code for - the subsystem. The packages are rooted at the org.springframework.webflow - root package in the package hierarchy. - - - - - Subsystem interfaces - Central API elements exposed by the subsystem, - typically through Java interfaces. - - - - - Internal dependencies - Dependencies of the subsystem. These could be - other subsystems of the layer or external libraries. - - - - - The Execution Core Layer (Bottom Layer) - - Defines core flow definition and execution public APIs. As the "bottom layer", this - layer is highly stable with no dependencies on any other layer. - - - Execution Core Subsystems - - - - - - - - - Subsystem name - Description - Packages - Subsystem interfaces - Internal dependencies - - - - - Core - - Foundational, generic types usable by all other subsystems. - Contains the default expression parser (OGNL-based) and - core collection types (AttributeMap and company). - - - core, - core.collection - - None - None - - - Util - - Low level utilities used by all other parts of the system. - - - util - - None - None - - - Flow Definition - - Central abstractions for modeling flow definitions. - These abstractions include FlowDefinition, - StateDefinition, and TransitionDefinition - that form the domain language for describing flows. - - - definition - - - FlowDefinition - - Core - - - Flow Definition Registry - - Support for working with registries of flow definitions. Flow - definitions eligible for execution are typically stored in - a registry that provides lookup services. - - - definition.registry - - - FlowDefinitionRegistry, - FlowDefinitionLocator - - - Core, - Flow Definition - - - - External Context - - Provides normalized access to a client environment that has called into Spring Web Flow. - - - context, - context.servlet, - context.portlet - - - ExternalContext - - - Core, - context.servlet requires Servlet API 2.4, - context.portlet requires Portlet API 1.0 in addition to Servlet API 2.4 - - - - Conversation - - Manages the creation and cleanup of conversational state. Used by - the execution repository system to begin new user conversations and - track execution state. - - - conversation, - conversation.impl - - - ConversationManager - - - Core, - Util, - External Context - - - - Flow Execution - - Stable runtime abstractions that define the flow definition - execution model. For executing flow definitions - and representing execution state. - - - execution, - execution.support, - execution.factory - - - FlowExecution - - - Core, - External Context, - Flow Definition - - - - Flow Execution Repository - - For persisting paused flow executions beyond a single request - into the server. - - - execution.repository, - execution.repository.support, - execution.repository.continuation - - - FlowExecutionRepository - - - Core, - Util, - Flow Definition, - Conversation, - Flow Execution - - - - Action - - Reusable action implementations. - - - action, - action.portlet - - - None - - - Core, - Util, - Flow Definition, - External Context, - Flow Execution - - - - -
-
- - The Execution Engine Layer - - Defines an implementation of the flow execution core API, forming the basis - of the state machine or "engine" implementation. More volatile, as it contains - specific implementations of stable execution abstractions. - - - Depends On: Execution Core - - - Execution Engine Subsystems - - - - - - - - - Subsystem name - Description - Packages - Subsystem interfaces - Internal dependencies - - - - - Engine Implementation - - The implementation of the flow execution engine based on a finite state machine. - - - engine, - engine.support, - engine.impl - - None - None - - - Flow Definition Builder - - Abstractions used at configuration-time for building and assembling Flow definitions - executable by this engine implementation. Flows are typically defined - in externalized resources such as XML files. - - - engine.builder, - engine.builder.xml - - - FlowBuilder - - - Engine Implementation, - Spring Beans 2.0, - Spring Context 2.0, - builder.xml requires JDK 1.5 or Xerces for XSD support - - - - -
-
- - The Test Layer - - Support for unit testing flow artifacts and system testing flow executions. - - - Depends On: Execution Engine, Execution Core - - - Test Subsystems - - - - - - - - - Subsystem name - Description - Packages - Subsystem interfaces - Internal dependencies - - - - - Engine Artifact Unit Test Support - - Support for unit testing implementations such as Actions in isolation. - - - test - - None - JUnit 3.8.1 - - - Flow Execution Test Support - - Support for testing Flow Executions out-of-container. - - - test.execution - - None - - Spring Beans 2.0, - JUnit 3.8.1 - - - - -
-
- - The Executor Layer - - Stable higher-level layer for driving and coordinating the execution of flow definitions. - This layer is decoupled from the more-volatile engine implementation. - - - Depends On: Execution Core - - - Executor Subsystems - - - - - - - - - Subsystem name - Description - Packages - Subsystem interfaces - Internal dependencies - - - - - Core - - Generic flow executor abstractions and support. - - - executor, - executor.support - - - FlowExecutor - - None - - - Spring MVC - - The integration between Spring Web Flow and the Spring MVC framework. - - executor.mvc - None - - Core, - Spring Web MVC 2.0 - - - - Struts - - The integration between Spring Web Flow and the Struts Classic framework. - - - executor.struts - - None - - Core, - Struts 1.1 - - - - -
-
- - The System Configuration Layer (Top Layer) - - The top-most layer for configuring the overall Spring Web Flow system for use - within an application. As the top layer, this layer depends on the most. - - - Depends On: Executor, Execution Engine, Execution Core - - - System Configuration Subsystems - - - - - - - - - Subsystem name - Description - Packages - Subsystem interfaces - Internal dependencies - - - - - Spring Configuration Support - - For configuring Spring Web Flow using Spring 1.x and 2.x. - - - config - - None - - Spring Beans 1.2.7, - spring-webflow-config-1.0 XSD support requires Spring 2.0 - - - - -
- - - - As described above, some subsystem packages are optional depending on your use of the - subsystem. For example, use of Spring Web Flow in a Servlet environment entails use of - the ExternalContext context.servlet package which requires the - Servlet API to be in the classpath. In this case, the context.portlet package is not - used and the Portlet API is not required. - - - - - For the exact list of dependencies, as well as supported product usage configurations, - see the Ivy dependency manager descriptor located within the SWF distribution. - -
-
- - Support - - Spring Web Flow 1.x is supported on Spring Framework 1.2.7 or > for the 1.x series, and - supported on 2.0 or > for the 2.x series. + Professional "from the source" support on Spring Web Flow is available from + SpringSource, the company behind Spring, and + Ervacon, operated by Web Flow project co-founder Erwin Vervaet - XML-based flow building requires Xerces 2 or JDK 5.0 (for XSD support). - - - Our active community support forum is located at http://forum.springframework.org. + Spring Community support is available at www.springframework.org
\ No newline at end of file diff --git a/spring-webflow/docs/reference/src/practical.xml b/spring-webflow/docs/reference/src/practical.xml deleted file mode 100644 index b7bb957e..00000000 --- a/spring-webflow/docs/reference/src/practical.xml +++ /dev/null @@ -1,2195 +0,0 @@ - - - Practical Use of Spring Web Flow - - Sample applications - - It is recommended that you review the Spring Web Flow sample applications included in the - release distribution for best-practice illustrations of the features of this framework. - A description of each sample is provided below: - - - - - - Phonebook - the original sample demonstrating most core features (including subflows). - - - - - Sellitem - demonstrates a wizard with conditional transitions, flow scope, flow execution redirects, and continuations. - - - - - Sellitem-JSF - The sellitem sample in a JSF environment - (notice how the flow definition is more concise because JSF components care for data binding and validation). - - - - - Shippingrate - demonstrates Spring Web Flow together with the Prototype Javascript framework (for Ajax-style flows). - - - - - 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. - - - - - Fileupload - demonstrates multipart file upload. - - - - - Birthdate - demonstrates Struts integration and the MultiAction. - - - - - Phonebook-Portlet - the phonebook sample in a Portlet environment - (notice how the flow definitions do not change). - - - - - - - Running the Web Flow sample applications - - The samples can be built from the command line and imported as Eclipse projects - all samples come - with Eclipse project settings. It is also possible to start by importing the samples into Eclipse - first and then build with Ant within Eclipse. - - - Building from the Command Line - - Java 1.5 (or greater) and Ant 1.6 (or greater) are prerequisites for building the sample applications. - Ensure those are present in the system path or are passed on the command line. To build Web Flow - samples from the command line, open a prompt, cd to the directory where Spring Web Flow was - unzipped, and run the following: - -cd projects/spring-webflow/build-spring-webflow -ant dist - - This builds all samples preparing "target" areas within each sample project subdirectory - containing webapp structures in both exploded and WAR archive forms. The build also provides basic helper targets - for deploying to Tomcat from Ant; however these webapp structures can be copied to any servlet container, - and each project is also a Eclipse Dynamic Web Project (DWP) for easy deployment inside Eclipse - with the Eclipse Webtools Project (WTP). - - - - Importing Projects into Eclipse - - Importing the sample projects into Eclipse is easy. With a new or an existing workspace select: - File > Import > Existing Projects into Workspace. In the resulting dialog, browse to the project - subdirectory where Spring Web Flow was unzipped and choose it as the root directory to import from. - Select OK. Here Eclipse will list all projects it found including the sample application projects. - Select the projects you're interested in, and select Finish. - - - If you previously built each project from the command line, Eclipse will compile with no errors. - If not, you will need to run the Ant build once for these errors to clear. - - - To build all projects inside Eclipse, import and expand the build-spring-webflow project, right-click on - build.xml and select Run As > Ant Build. - Doing this will run the default Ant target and will build all sample projects. - - - To build a single project inside Eclipse, simply select the project, right-click, and - select Run As > Ant Build. You can also use the convenient - shortcut ALT + SHIFT + X (Execute menu), then Q (Run Ant Build). - - - After Ant runs and the libraries needed to compile each project are downloaded, - all errors in the Eclipse problems view should go away. Try refreshing a project (F5) - if you still have errors. In general, from this point on you no longer need Ant: you - can rely on Eclipse's incremental compile and Eclipse's web tools (WTP) built-in JEE support - for deployment. (Ant is only needed in the system for command-line usage or when the list of - jar dependencies for a project changes and new jars need to be downloaded). - - - - Deploying projects inside Eclipse using Eclipse Web Tools (WTP) - - Each Spring Web Flow sample application project is a Eclipse Dynamic Web Project (DWP), - for easy deployment to a server running inside the Eclipse IDE. To take advantage - of this, you must be running Eclipse 3.2 with Web Tools 1.5. - - - To run a sample application as a webapp inside Eclipse, simply select the project, - right-click, and select Run -> Run On Server. A convenient - shortcut for this action is ALT + SHIFT + X (Execute menu), R (Run on Server). - The first time you do this you will be asked to setup a Server, where you are - expected to point Eclipse to a location where you have a Servlet Container - such as Apache Tomcat installed. Once your container has been setup and you finish the - deployment wizard, Eclipse will start the container and automatically publish - your webapp to it. In addition, it will launch a embedded web browser allowing you - to run the webapp fully inside the IDE. - - - - Other IDE's - - Importing samples into other IDE's should be fairly straight-forward. If using another IDE, - running the Ant build from the command line first may help as it will populate the lib - subdirectories of each sample project. Follow steps similar as those outlined for Eclipse above. - - - - - Sellitem Example - - Overview - - The Sellitem example demonstrates using Web Flow to build a - shopping cart wizard with - a shipping rate subflow, decision states, service and data access - Spring POJO beans, Spring 2.0 form tags, and a Web Flow - FormAction bean for data binding, validation, and - error reporting. - - - The Sellitem example breaks down its Spring application configuration - into a number of files organized according to purpose. - Although the example itself uses a small number of beans you - may consider organizing a real-world application (with many more - beans) according to similar principles. Before going into the specifics - of each individual context, use the diagram below to - get a brief overview of all configuration files including - location and purpose. - - - - - - - - - - Sellitem Spring & Web Flow Application Wiring - - - - - - Web.xml - - The web.xml configuration maps "*.htm" requests to the sellitem servlet - - a Spring MVC DispatcherServlet: - -<servlet> - <servlet-name>sellitem</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <init-param> - <param-name>contextConfigLocation</param-name> - <param-value> - /WEB-INF/sellitem-servlet-config.xml - /WEB-INF/sellitem-webflow-config.xml - </param-value> - </init-param> -</servlet> - -<servlet-mapping> - <servlet-name>sellitem</servlet-name> - <url-pattern>*.htm</url-pattern> -</servlet-mapping> - - The contextConifgLocation parameter for the DispatcherServlet indicates the - Spring MVC web context for the sellitem servlet is spread over two xml files: - sellitem-servlet-config.xml and sellitem-webflow-config.xml. - The web.xml also requests an additional Spring context to be loaded - from the classpath through the ContextLoaderListener: - -<context-param> - <param-name>contextConfigLocation</param-name> - <param-value> - classpath:org/springframework/webflow/samples/sellitem/services-config.xml - </param-value> -</context-param> - -<listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -</listener> - - This service layer context defines beans to be referenced from - web flow definitions. The next section discusses the - content of this context in more detail. - - - - Services-config.xml - - The services-config.xml loaded from the classpath through Spring MVC's - ContextLoaderListener defines several beans for the service - and data access layers of the application. For example, - the service context defines a DAO bean ("saleProcessor") and injects - it with a data source: - -<bean id="saleProcessor" class="org.springframework.webflow.samples.sellitem.JdbcSaleProcessor"> - <property name="dataSource" ref="dataSource"/> -</bean> - -<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> - <property name="driverClassName" value="org.hsqldb.jdbcDriver"/> - <property name="url" value="jdbc:hsqldb:mem:sellItem"/> - <property name="username" value="sa"/> -</bean> - - The services context also declares a bean of type InMemoryDatabaseCreator - set to autowire by type meaning that its fields will be compared against the types of - beans available in the context and will be automatically set when a match is found. - Hence the dataSource bean is used to set the dataSource property - of InMemoryDatabaseCreator: - -<bean id="databaseCreator" class="org.springframework.webflow.samples.sellitem.InMemoryDatabaseCreator" - autowire="byType"/> - - Looking inside the InMemoryDatabaseCreator, its initDao() method invoked - during context initialization creates a table called T_SALES for use by the sample - application. This table is created in an in-memory hsqldb database called - sellitem (based on the url property of the dataSource bean). - It's also worth noting the bean declarations related to declarative - transaction management: - -<tx:annotation-driven/> - -<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> - <property name="dataSource" ref="dataSource"/> -</bean> - - The "<tx:annotation-driven>"declaration indicates transaction - configuration is governed by Java 5 annotations used in bean classes - such as this annotation in the SaleProcessor interface: - -@Transactional -public interface SaleProcessor { - public void process(Sale sale); -} - - For annotated beans the Spring container automatically creates - proxies according to the transaction semantics in the annotation - metadata. The "<tx:annotation-driven>" tag has a transaction-manager - attribute but this attribute is not required if the transaction - manager bean is named "transactionManager". - - - - Spring MVC Context - - The Spring MVC web context is split over two files - - sellitem-servlet-config.xml and sellitem-webflow-config.xml. - The sellitem-servlet-config.xml defines - a controller and a view resolver. - -<bean name="/pos.htm" class="org.springframework.webflow.executor.mvc.FlowController"> - <property name="flowExecutor" ref="flowExecutor" /> -</bean> - -<!-- Maps flow view-state view names to JSP templates --> -<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> - <property name="prefix" value="/WEB-INF/jsp/" /> - <property name="suffix" value=".jsp" /> -</bean> - - FlowController is a web flow controller extending Spring MVC's AbstractController - delegating requests (in this case for the "/pos.htm" servlet path) to the - flowExecutor bean it is configured with. FlowController acts - as gateway to Web Flow and a single controller instance can serve - the application as most of the actual control logic is encapsulated - in web flow definitions. - - - The sellitem-webflow-config.xml defines web flow specific beans such as - a flow executor, a flow registry and a flow listener beans: - -<!-- Launches new flow executions and resumes existing executions --> -<flow:executor id="flowExecutor" registry-ref="flowRegistry"> - <flow:execution-listeners> - <flow:listener ref="listener" criteria="sellitem-flow" /> - </flow:execution-listeners> -</flow:executor> - -<!-- Creates the registry of flow definitions for this application --> -<flow:registry id="flowRegistry"> - <flow:location path="/WEB-INF/flows/**/*-flow.xml" /> -</flow:registry> - -<!-- Observes the lifecycle of sellitem-flow executions --> -<bean id="listener" - class="org.springframework.webflow.samples.sellitem.SellItemFlowExecutionListener" /> - - The FlowExecutor is the central entry point into the - Spring Web Flow system. It drives the execution of flow definitions - configured through the flowRegistry. The flowRegistry bean is configured - to load definitions from files ending with "-flow.xml" in any - subdirectory of /WEB-INF/flows. This matches to - sellitem-flow.xml, shipping-flow.xml, sellitem-simple-flow.xml, - sellitem-conversation-scope-flow.xml and shipping-conversation-scope-flow.xml. - - - As shown here the flow executor can also be configured with a flow - listener, which is a callback mechanism for flow execution lifecycle events. - The SellItemFlowExecutionListener extends FlowExecutionListenerAdapter - - a default implementation of the FlowExecutionListener interface - sparing the need to implement methods for all lifecycle events. - - - Looking inside SellItemFlowExecutionListener, it implements the stateEntering - method executed for whenever a new state is about to be entered. - The logic in this method checks if the current web flow state - has an attribute named "role" and if so it ensures the user - has that role: - -String role = nextState.getAttributes().getString("role"); -if (StringUtils.hasText(role)) { - HttpServletRequest request = ((ServletExternalContext)context.getExternalContext()).getRequest(); - if (!request.isUserInRole(role)) { - throw new EnterStateVetoException(context.getActiveFlow().getId(), context.getCurrentState().getId(), - nextState.getId(), "State requires role '" + role - + "', but the authenticated user doesn't have it!"); - } -} - - - - Based on the above definitions - web.xml, Spring MVC controller bean, and - web flow registry, the sellitem-flow can be initiated with the - following URI: - -/swf-sellitem/pos.htm?_flowId=sellitem-flow - - - Note: although it is possible to invoke the shipping-flow directly as well, - it expects an input attribute and is intended to be invoked as a subflow. - - - - - Sellitem-beans.xml - - Before tracing the sequence of states in sellitem-flow.xml notice the - import declaration at the bottom of that file: - -<import resource="sellitem-beans.xml"/> - - The sellitem-beans.xml located in the same directory declares a - web flow FormAction bean for use in the flow definition and configures - it with a SaleValidator and a SellItemPropertyEditorRegistrar: - -<!-- Manages setting up, binding input to, and validating a Sale "backing wizard form object" --> -<bean id="formAction" class="org.springframework.webflow.action.FormAction"> - <property name="formObjectName" value="sale"/> - <property name="validator"> - <bean class="org.springframework.webflow.samples.sellitem.SaleValidator"/> - </property> - <!-- Installs property editors used to format non-String fields like 'shipDate' --> - <property name="propertyEditorRegistrar"> - <bean class="org.springframework.webflow.samples.sellitem.SellItemPropertyEditorRegistrar"/> - </property> -</bean> - - The SellValidator will be used to validate form input data. - The SellItemPropertyEditorRegistrar is responsible for registering - custom property editors. Such editors are used to bind text data from - HTML form fields to server-side Objects. For example - SellItemPropertyEditorRegistrar registers a custom date - editor: - -public void registerCustomEditors(PropertyEditorRegistry registry) { - registry.registerCustomEditor(Date.class, - new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"), true)); -} - - This editor will bind the shipDate form field in shippingDetailsForm.jsp - to the shipDate property of the Sale object on the server side. - - - - Sellitem-flow Flow Definition - - The flow begins by declaring a "sale" variable - an object of type Sale: - -<var name="sale" class="org.springframework.webflow.samples.sellitem.Sale"/> - - The formAction bean will use the sale variable for form binding and - validation (see sellitem-beans.xml). - - - The start state for the flow enterPriceAndItemCount is a view state, which resolves - to the JSP page /WEB-INF/jsp/priceAndItemCountForm.jsp: - -<view-state id="enterPriceAndItemCount" view="priceAndItemCountForm"> - <render-actions> - <!-- create the backing form object and initialize a empty errors collection --> - <action bean="formAction" method="setupForm"/> - </render-actions> - <transition on="submit" to="enterCategory"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validatePriceAndItemCount"/> - </action> - </transition> -</view-state> - - The view state uses a render action to invoke the setupForm method of the - formAction bean. The setupForm method prepares a form object based on - the "sale" variable declared at the top of the flow definition. - - - The priceAndItemCountForm.jsp page collects a price and an itemCount using - Spring 2.0 form input tags binding form fields to properties in the form - backing object "sale". When pressed, the submit button "_eventId_submit" - causes a web flow transition for an event with the id of "submit" to - the view state "enterCategory". Prior to transitioning the formAction's - bindAndValidate method is called to perform binding and (partial) validation - using the validatePriceAndItemCount method of the validator object. - - - The next view state enterCategory (based on categoryForm.jsp) - collects inputs for sale category and whether shipping is required. On - submit it transitions to the requiresShipping state: - -<view-state id="enterCategory" view="categoryForm"> - <transition on="submit" to="requiresShipping"> - <action bean="formAction" method="bind"/> - </transition> -</view-state> - - The requiresShipping state is a decision state making - flow routing decisions. It evaluates a boolean expression against the - executing flow and it decides where to transition to next. - Here the shipping boolean property of the "sale" form backing - object is checked to decide whether to go to the enterShippingDetails - subflow state or proceed directly to processSale. - -<decision-state id="requiresShipping"> - <if test="${flowScope.sale.shipping}" then="enterShippingDetails" else="processSale"/> -</decision-state> - - The enterShippingDetails subflow state is based on shipping-flow.xml - located in the same directory. The form backing object "sale" is - passed to it as an input attribute using an attribute mapper declaration: - -<subflow-state id="enterShippingDetails" flow="shipping-flow"> - <attribute-mapper> - <input-mapper> - <input-attribute name="sale"/> - </input-mapper> - </attribute-mapper> - <transition on="finish" to="processSale"/> -</subflow-state> - - The shipping-flow subflow is a simple flow with one view state. It - collects the shipping details, binds the data and returns to its parent - flow. The id of the subflow end state "finish" is returned to the - parent subflow state causing a transition to the processSale action state. - -<action-state id="processSale"> - <bean-action bean="saleProcessor" method="process"> - <method-arguments> - <argument expression="flowScope.sale"/> - </method-arguments> - </bean-action> - <transition on="success" to="finish"/> -</action-state> - - The saleProcessor bean, a POJO defined in services-config.xml - is invoked using a "bean-action" declaration (as opposed to the "action" - declation used to invoke a web flow Action such as FormAction). - The saleProcessor (an instance of JdbcSaleProcessor) performs a database - update using the values of the Sale object and upon - successful completion transitions to the end view state: - -<end-state id="finish" view="costOverview"> - <entry-actions> - <action bean="formAction" method="setupForm"/> - </entry-actions> -</end-state> - - Then end state calls FormAction's setupForm method again. - This does not re-create the "sale" form object (still in flow scope) - but it does ensure any custom property editors are - registered for use in rendering the JSP. - - - - Sellitem-simple-flow Flow Definition - - A simpler version of the sellitem-flow is available in the sellitem-simple-flow.xml file. - This version uses a view state to gather shipping details instead of using a subflow. You - can launch the sellitem-simple-flow using the following URI: - -/swf-sellitem/pos.htm?_flowId=sellitem-simple-flow - - - - - Sellitem-conversation-scope-flow Flow Definition - - This web flow is equivalent in functionality to the sellitem-flow definition - described above. The main difference is that it uses "conversation" - scope to store the form backing object declared in - /WEB-INF/flows/converstation-scope/sellitem-beans.xml. - -<bean id="formAction" class="org.springframework.webflow.action.FormAction"> - <property name="formObjectName" value="sale"/> - <property name="formObjectScope" value="CONVERSATION"/> - <property name="formErrorsScope" value="CONVERSATION"/> - - Conversation scope retains attributes stored in it for the life - of the flow execution and is shared by all flow sessions. - For example when invoking the shipping details subflow the parent - flow does not need to pass the "sale" form backing object because - it is now stored in conversation scope and is accessible to both flows: - -<subflow-state id="enterShippingDetails" flow="shipping-conversation-scope-flow"> - <transition on="finish" to="processSale"/> -</subflow-state> - - Also, when the "sale" object needs to be accessed it is done by referencing - conversation cope: - -<decision-state id="requiresShipping"> - <if test="${conversationScope.sale.shipping}" then="enterShippingDetails" else="processSale"/> -</decision-state> - - You can launch the sellitem-conversation-scope-flow using the following URI: - -/swf-sellitem/pos.htm?_flowId=sellitem-conversation-scope-flow - - - - - - Sellitem-JSF Example - - Overview - - The Sellitem-JSF example uses Web Flow and JSF to build a shopping - cart wizard. Navigation logic and supporting managed beans - are supplied by Spring Web Flow, while UI views and - overall servlet processing is based on JSF technology. - - - - The underlying Web Flow definitions for the Sellitem and the Sellitem-JSF - examples are very similar. To avoid repetition the documentation for - the Sellitem-JSF example focuses primarily on the points of integration between - Web Flow and JSF. For further general information on Web Flow definitions - and supporting Java classes for the Sellitem example, please refer to the - Sellitem example documentation. - - - - - Web.xml - - The web.xml contains standard JSF configuration including mappings for - the JSF front servlet: it handles all requests ending with "*.faces": - -<!-- Faces Servlet --> -<servlet> - <servlet-name>Faces Servlet</servlet-name> - <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> - <load-on-startup>1</load-on-startup> -</servlet> - -<servlet-mapping> - <servlet-name>Faces Servlet</servlet-name> - <url-pattern>*.faces</url-pattern> -</servlet-mapping> - - - - In addition, the web.xml loads a Spring root web application context containing the services - used by the application: - -<context-param> - <param-name>contextConfigLocation</param-name> - <param-value> - classpath:org/springframework/webflow/samples/sellitem/services-config.xml - /WEB-INF/webflow-config.xml - </param-value> -</context-param> - -<listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -</listener> - - The services-config.xml contains POJO beans required for the services and - data access layers of the application. These declarations are very similar - to the Sellitem example (and explained in more detail there). - The webflow-config.xml contains Web Flow related bean - definitions. These definitions will be explained a little bit - further on in the context of how they fit into the JSF phases - lifecycle. - - - - Web Flow JSF Setup in faces-config.xml - - To plug in Web Flow, a few things must be added once to faces-config.xml. - This is demonstrated in the faces-config.xml of Sellitem-JSF: - -<application> - <navigation-handler>org.springframework.webflow.executor.jsf.FlowNavigationHandler</navigation-handler> - <variable-resolver>org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver</variable-resolver> -</application> - -<lifecycle> - <phase-listener>org.springframework.webflow.executor.jsf.FlowPhaseListener</phase-listener> -</lifecycle> - - - - The FlowNavigationHandler delegates view navigation handling to the - the Web Flow system when a flow is initiated or resumed. - - - The DelegatingFlowVariableResolver is suitable for use along side - other variable resolvers to support EL binding expressions like - {#bean.property} where "bean" could be a property in any supported scope. - The resolver search algorithm looks in flash scope first, then flow scope, - then conversation scope. If no variable is found, this resolver - delegates to the next resolver in the chain. - - - The FlowPhaseListener invoked during beforePhase and afterPhase JSF events - is responsible for managing the lifecycle of a FlowExecution and making it available - to other JSF artifacts during the lifecycle of a JSF request. - - - - Web Flow System Setup in webflow-config.xml - - Examining the definitions in faces-config.xml highlighted the ability - to use plug Web Flow in as a navigation handler and as a source - for JSF managed beans. Now we can turn to the question - of how to configure the web flow system itself in a JSF environment. - - - The Spring web context fragment /WEB-INF/webflow-config.xml contains the following configuration: - -<!-- 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/flows/sellitem-flow.xml" /> -</flow:registry> - - Here the flow executor is configured to support execution of a single - flow definition - sellitem-flow.xml. The executor bean has been assigned the id - "flowExecutor". This id is significant and is required for the JSF artifacts to detect - the executor and its services. - - - - Launching the sellitem-flow - - The intro.jsp page shows how the configured web flow sellitem-flow.xml can be launched using - a JSF command link component. - -<h:form> - <h:commandLink value="Sell Item" action="flowId:sellitem-flow"/> -</h:form> - - This causes the sellitem-flow to be initiated. Once a flow is initiated - each subsequent JSP page can participate in the flow (the flow execution key - is tracked for you). - - - A few notable differences between Sellitem and Sellitem-JSF to keep in mind: - - - - The JSF version of the sellitem flow definition is simpler because JSF components care for data binding and validation. - - - - - In its web flow definition Sellitem-JSF uses actual JSP names (instead of the logical view names used in Sellitem) - to be rendered by JSF. This is consistent with normal JSF-isms. - - - - - The JSP pages in Sellitem-JSF use unified EL to access the converastion scoped Sale object - e.g. #{sale.price}. - - - - Sellitem-JSF uses JSF component tags for UI and Sellitem uses Spring form tags. - - - - There is no need to manually track the flow execution key because it is tracked for you in the JSF view root. - - - - The combination of delegating flow variable resolution plus automatic flow execution key management - means JSF views selected a flow look like standard JSF views to JSF developers. Also, JSF components - help simplify flow definition logic as the flow no longer has to worry about data binding and validation. - - - For more information and understanding on the Sellitem flow definition logic itself - please refer to the documentation for the original Sellitem example. - - - - - Shippingrate Example - - Overview - - The Shippingrate sample demonstrates the use of Spring Web Flow in combination with - Ajaxian techniques. It consists of several wizard-style steps executed - with Ajax requests and refreshing a portion of the page. - The input is collected from the user in incremental steps. It is stored - in a flow-scoped object and is then used to calcualte a shipping rate. - The example also demonstrates invocation of a service-layer bean - defined in a Spring context to perform calculations and - to provide reference data such as countries and package types. - - - - Web.xml - - The web.xml configuration maps requests for "*.htm" to the - shippingrate servlet - a regular Spring MVC DispatcherServlet: - -<servlet> - <servlet-name>shippingrate</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> -</servlet> - -<servlet-mapping> - <servlet-name>shippingrate</servlet-name> - <url-pattern>*.htm</url-pattern> -</servlet-mapping> - - The web.xml also ensures the following Spring context file is loaded - at runtime from the web application classpath: - -<context-param> - <param-name>contextConfigLocation</param-name> - <param-value> - classpath:org/springframework/webflow/samples/shippingrate/domain/services.xml - </param-value> -</context-param> - - The services.xml Spring context defines a "rateService" bean providing - operations for making shipping rate calculations and for retrieving - reference data required for display in the JSP pages of the application. - - - - Spring MVC Context - - The Spring MVC servlet context for the shippingrate servlet (WEB-INF/shippingrate-servlet.xml) - defines one controller bean: - -<bean name="/rates.htm" class="org.springframework.webflow.executor.mvc.FlowController"> - <property name="flowExecutor" ref="flowExecutor" /> -</bean> - - FlowController is a Web Flow controller. It is the main point of integration between Spring MVC - and Spring Web Flow routing requests to one or more managed web flow executions. The - FlowController is injected with flowExecutor and flowRegistry beans: - -<!-- Launches new flow executions and resumes existing executions. --> -<flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="simple"/> - -<!-- Creates the registry of flow definitions for this application --> -<flow:registry id="flowRegistry"> - <flow:location path="/WEB-INF/flows/**/*-flow.xml" /> -</flow:registry> - - The flowExecutor and the flowRegistry beans collectively configure - the FlowController with one web flow - the getRate-flow defined in - /WEB-INF/flows/getRate-flow.xml. The flowExecutor uses a "simple" - repository, which manages execution state in the user session. - - - Given the above definitions the following URI can be used to initiate - the getRate-flow: - -/swf-shippingrate/rates.htm?_flowId=getRate-flow - - - - - Ajax Requests - - The shippingrate example consists of several wizard-style steps. - After the initial index.jsp subsequent pages are - loaded in an Ajax manner without reloading the entire page. - - - The Ajax requests are done with the help of the - Prototype - framework and a thin JavaScript layer over it providing - convenient functions for processing Ajax form and get requests. - The required Javascript libraries are included in index.jsp as follows: - -<script src="prototype.js" type="text/javascript"></script> -<script src="swf_ajax.js" type="text/javascript"></script> - - - - When index.jsp is loaded the following JavaScript invokes the getRate-flow - and replaces the content of the getRateWizard div tag with the response - returned from the server: - -<div id="getRateWizard"> - <script type="text/javascript"> - window.onload = function() { - new SimpleRequest('getRateWizard', 'rates.htm', 'get', '_flowId=getRate-flow'); - }; - </script> -</div> - - Functions are first-class citizens and a type in JavaScript. - The script above creates an instance of - the SimpleRequest function defined in swf_ajax.js. This function invokes - Prototype's Ajax.Updater with the specified URL and request parameters. On success - the content of the getRateWizard div is replaced with the response returned - from the server. On failure such as an HTTP response code other 200 (OK) - an error message is displayed. - - - The next few pages are form-based JSP's - selectCustomer.jsp, selectReceiver.jsp, - etc. Each of them contains the following JavaScript call at the bottom: - -<script type="text/javascript"> - formRequest('selectCustomerTypeForm'); -</script> - - The formRequest function is also defined in swf_ajax.js - and it uses Prototype to register a handler for the form submit event: - -function formRequest(formElementId) { - Event.observe(formElementId, 'submit', handleSubmitEvent, true); -} - - The handleSubmitEvent function extracts the form parameters, stops the - submit event, and posts an AJAX request via XMLHttpRequest. On success - the results returned form the server replace the content of the form. - On failure such as an HTTP response code other 200 (OK) an error - message is displayed. - - - Although not demonstrated in this example a back button can be - implemented in parallel with the Next button used to advance from - one screen to the next. This would be necessary because the browser - back button - a common issue in Ajax applications, contrary to user - expectation returns to the page prior to the first Ajax request. - - - As a result of the Ajax requests the entire wizard is able to - function within a portion of the page without refresing - the remaining information on it. - - - - getRate Web Flow - - The getRate-flow (/WEB-INF/jsp/flows/getRate-flow.xml) defines the following start state: - -<view-state id="selectCustomerType" view="selectCustomer"> - <transition on="submit" to="selectSender"> - <action bean="formAction" method="bind" /> - </transition> -</view-state> - - This is a view state, which will display the initial form using the - JSP page /WEB-INF/jsp/selectCustomer.jsp. Notice, the use of a start action - executed immediately before the JSP is displayed: - -<start-actions> - <action bean="formAction" method="setupForm" /> -</start-actions> - - The "formAction" bean is defined in the Spring servlet context - (/WEB-INF/shippingrate-servlet.xml). It specifies a form object - and a validator to use for form data binding and validation: - -<!-- Performs "form backing object" data binding and validation on input submit --> -<bean id="formAction" class="org.springframework.webflow.action.FormAction"> - <property name="formObjectName" value="rateCriteria" /> - <property name="formObjectClass" value="org.springframework.webflow.samples.shippingrate.domain.RateCriteria" /> - <property name="formObjectScope" value="FLOW" /> - <property name="validator"> - <bean class="org.springframework.webflow.samples.shippingrate.domain.RateCriteriaValidator" /> - </property> -</bean> - - The form object of type RateCriteria will be used to collect data - from the user in several steps. The form object will be stored in FLOW scope - and will not be re-created with each request as long - as the flow hasn't reached its end state. The actual binding of - html form fields to the RateCriteria object is based on - Spring's data binding mechanism. Html form fields are surrounded - with the <spring:bind> tag containing the path - nested property field. FormAction's bindAndValidate method - will initiate the actual binding on the server side - between HTTP request parameters and RateCriteria data fields. - - - When the selectCustomer.jsp submits back to the FlowController via - "/swf-shippingrate/rate.htm" it uses a submit button named - "_eventId_submit". This indicates to Web Flow a transition to - the "selectSender" view state. This view state is defined as follows: - -<view-state id="selectSender" view="selectSender"> - <render-actions> - <bean-action bean="rateService" method="getCountries"> - <method-result name="countries" /> - </bean-action> - </render-actions> - <transition on="submit" to="selectReceiver"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validateSender" /> - </action> - </transition> -</view-state> - - The selectSender view state has a render action: - the "rateService" bean that was loaded through the services.xml context referenced - in web.xml. The purpose of the render action is to load data required - to render the JSP. In this case the rateService bean has a method called - getCountries that returns a list of countries to be displayed in a drop-down - by the JSP. - - - The "selectSender" view state also defines one transition: on event with - id of "submit" a transition to the "selectReceiver" view state occurs. - A pre-requisite for the transition to occur is the successful completion of - formAction bean's bindAndValidate method. The attribute "validatorMethod" on - the bean specifies the name of the method to invoke on the Validator object - specifically for the fields of the current screen. - If the bindAndValidate method does not succeed the transition does not take - place and the flow remains in the "selectSender" view - state where the user can review the errors and modify the selection. - - - The next two states in the flow - selectReceiver and selectPackageDetails use similar - mechnisms. The rateSevice bean is used to retrieve countries and package types for - use in the JSP. The form backing object RateCriteria stored in FLOW scope - is used to collect user input with each form submit. - - - The "findRate" action state occurs after all user input has been provided. - It is defined as follows: - -<action-state id="findRate"> - <bean-action bean="rateService" method="getRate"> - <method-arguments> - <argument expression="flowScope.rateCriteria" /> - </method-arguments> - <method-result name="rate" /> - </bean-action> - <transition on="success" to="showRate" /> -</action-state> - - Logic for the action state is provided by the getRate method of - the rateService bean. The RateCriteria object stored in FLOW scope - and containing the user input is passed to the rateService bean. - The result of the method is exposed in request scope under - the name "rate". - - - The next and final state "showRate" is a JSP page, which accesses the calculated rate - information and displays it to the user. - - - - - Numberguess Example - - Overview - - Numberguess uses Web Flow to implement two number guessing games. - For each game the user can enter multiple guesses and depending - on the answer either transition back to the same screen or - advance to the final screen. Logic for the guessing games is - provided through FLOW-scoped beans, which also maintain state - such as the total number of guesses. The example defines transitions - using event pattern matching and custom exception handlers. - - - - Web.xml - - The web.xml configuration maps "*.htm" requests to the numberguess servlet - - a regular Spring MVC DispatcherServlet: - -<servlet> - <servlet-name>numberguess</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> - <init-param> - <param-name>contextConfigLocation</param-name> - <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> - </init-param> -</servlet> - -<servlet-mapping> - <servlet-name>numberguess</servlet-name> - <url-pattern>*.htm</url-pattern> -</servlet-mapping> - - The Spring web context is loaded from a file called - /WEB-INF/dispatcher-servlet.xml. - - - - Spring MVC Context - - The Spring MVC web context (WEB-INF/dispatcher-servlet.xml) - defines one controller bean: - -<bean name="/play.htm" class="org.springframework.webflow.executor.mvc.FlowController"> - <property name="flowExecutor" ref="flowExecutor" /> -</bean> - - FlowController is a Web Flow controller. It is the main point of - integration between Spring MVC and Spring Web Flow routing requests - to one or more managed web flow executions. The FlowController is - injected with flowExecutor and flowRegistry beans: - -<!-- Launches new flow executions and resumes existing executions. --> -<flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="singlekey"/> - -<!-- Creates the registry of flow definitions for this application --> -<flow:registry id="flowRegistry"> - <flow:location path="/WEB-INF/higherlower.xml" /> - <flow:location path="/WEB-INF/mastermind.xml" /> -</flow:registry> - - The flowExecutor and the flowRegistry beans collectively configure - the FlowController with two web flows - higherlower and mastermind. - This flowExecutor is configured with a simple repository that assigns - a single flow execution key per conversation. The key, once assigned, - never changes for the duration of the conversation. - - - Given the above definitions the following URI's can be used to initiate - each of the two flows: - -/swf-numberguess/play.htm?_flowId=higherlower -/swf-numberguess/play.htm?_flowId=mastermind - - - - The Spring MVC servlet context also defines a view resolver bean for - resolving logical view names. In general Web Flow does not aim - to replace the flexibility of Spring MVC for view resolution. - It focuses on the C in MVC. - - - - Higherlower Flow - - The Higherlower flow (/WEB-INF/higherlower.xml) starts with the following - flow variable declaration: - -<var name="game" class="org.springframework.webflow.samples.numberguess.HigherLowerGame"/> - - This variable is automatically created when an execution of the flow - begins and will exist in FLOW scope throughout its duration. - - - The start state for the flow is defined as follows: - -<view-state id="enterGuess" view="higherlower.enterGuess"> - <transition on="submit" to="makeGuess"/> -</view-state> - - The view resolver bean of Spring MVC will resolve "higherlower.enterGuess" - to /WEB-INF/jsp/higherlower.enterGuess.jsp. - This JSP has a form with one input field for the guess number. - The "game" variable referenced throughout the JSP - is the FLOW-scoped variable that was declared at the top of - the flow definition. - - - The name of the form submit button "_eventId_submit" indicates the - event id to use for deciding where to transition to next. Given an - event with id of "submit" the "enterGuess" view state transitions - to the "makeGuess" action state defined as follows: - -<action-state id="makeGuess"> - <evaluate-action expression="flowScope.game.makeGuess(requestParameters.guess)"> - <evaluation-result name="guessResult"/> - </evaluate-action> - <transition on="CORRECT" to="showAnswer"/> - <transition on="*" to="enterGuess"/> - <transition on-exception="java.lang.NumberFormatException" to="enterGuess"/> -</action-state> - - - - The makeGuess action state consists of one evaluate action and three - transitions. Evaluate actions are used to invoke logic encapsulated - in a FLOW-scoped object - in this case the game bean. - The makeGuess method of the game bean returns one of several enum - values it defines: - -enum GuessResult { - TOO_HIGH, TOO_LOW, CORRECT, INVALID -} - - Web Flow detects the returned result from the makeGuess method - is a JDK 1.5 enum type and - creates an Event with a String id matching the enum value. If the - makeGuess method returns CORRECT a transition to the final - showAnswer state occurs. For any other event (defined with the event - pattern on="*") Web Flow returns to the enterGuess - state. The makeGuess state also defines one on-exception transition - demonstrating how specific Exceptions can be incorporated into - flow transition logic. - - - The end-state showAnswer resolves to the JSP page - /WEB-INF/jsp/higherlower.showAnswer.jsp, which simply shows the - correct guess. At this point the flow has ended and the "game" bean - is no longer in scope. - - - - Mastermind Flow - - The mastermind flow uses a similar flow definition to implement a 4-digit - guessing game: - -<var name="game" class="org.springframework.webflow.samples.numberguess.MastermindGame"/> - -<start-state idref="enterGuess"/> - -<view-state id="enterGuess" view="mastermind.enterGuess"> - <transition on="submit" to="makeGuess"/> -</view-state> - -<action-state id="makeGuess"> - <evaluate-action expression="flowScope.game.makeGuess(requestParameters.guess)"> - <evaluation-result name="guessResult"/> - </evaluate-action> - <transition on="CORRECT" to="showAnswer"/> - <transition on="*" to="enterGuess"/> -</action-state> - -<end-state id="showAnswer" view="mastermind.showAnswer"/> - - The MastermindGame class encapsulates the logic for the game and - is stored as a FLOW-scoped bean. - It returns one of three possible enum values - - WRONG, CORRECT, or INVALID, which Web Flow converts to events with - id's matching the enum values. If the guess is INVALID the JSP page - /WEB-INF/jsp/mastermind.enterGuess.jsp will print an error message. - If the guess is CORRECT the flow will transition to the showAnswer - end state and complete the flow. - - - - - 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. - - - - - Itemlist 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="requestParameters.data" target="item" /> - </output-mapper> -</end-state> - - With the above declarations we see how a subflow can pass output - parameters back to its parent flow - in this case the 'data' request parameter - is passed back as an output parameter. - - - 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. - - - - - Fileupload Example - - Overview - - Fileupload is a simple one page web application for uploading files to a server. It is based - on Spring MVC, uses a Web Flow controller and one web flow with two states: a view state for - displaying the initial JSP page and an action state for processing the submit. - - - - Web.xml - - The web.xml configuration maps requests for "*.htm" to the fileupload servlet - a regular - Spring MVC DispatcherServlet: - -<servlet> - <servlet-name>fileupload</servlet-name> - <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> -</servlet> - -<servlet-mapping> - <servlet-name>fileupload</servlet-name> - <url-pattern>*.htm</url-pattern> -</servlet-mapping> - - - - - Spring MVC Context - - The Spring MVC servlet context for the fileupload servlet (WEB-INF/fileupload-servlet.xml) defines - one controller bean: - -<bean name="/admin.htm" class="org.springframework.webflow.executor.mvc.FlowController"> - <property name="flowExecutor" ref="flowExecutor" /> -</bean> - - FlowController is a Web Flow controller. It is the main point of integration between Spring MVC - and Spring Web Flow routing requests to one or more managed web flow executions. The - FlowController is injected with flowExecutor and flowRegistry beans containing one web flow - definition: - -<!-- Launches new flow executions and resumes existing executions. --> -<flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="singlekey"/> - -<!-- Creates the registry of flow definitions for this application --> -<flow:registry id="flowRegistry"> - <flow:location path="/WEB-INF/fileupload.xml" /> -</flow:registry> - - Given the above definitions the following URI can be used to invoke the "fileupload" flow: - -/swf-fileupload/admin.htm?_flowId=fileupload - - - - Both flowExecutor and flowRegistry beans are defined with Spring custom tags schema available in - Spring 2.0. The custom tags make configuration less verbose and more readable. Regular Spring - bean definitions can be used as well with earlier versions of Spring. - - - The Spring MVC context also defines a view resolver bean for resolving logical view names and a - multipartResolver bean for the upload component. In general Web Flow does not aim to replace the - flexibility of Spring MVC for view resolution. It focuses on the C in MVC. - - - - Fileupload Web Flow - - The start state for the fileupload flow (WEB-INF/fileupload.xml) is a view state: - -<start-state idref="selectFile"/> - -<view-state id="selectFile" view="fileForm"> - <transition on="submit" to="uploadFile"/> -</view-state> - - View states allow a user to participate in a flow by presenting a suitable interface. - The view attribute "fileForm" is a logical view name, which the Spring MVC view resolver bean - will resolve to /WEB-INF/jsp/fileForm.jsp. - - - The fileForm.jsp has an html form that submits back to the same controller - (/swf-fileupload/admin.htm) and passes a "_flowExecutionKey" parameter. - The value for _flowExecutionKey is provided by the FlowController - it identifies the current - instance of the flow and allows Web Flow to resume flow execution, which is paused each time a - view is displayed. - - - The name of the form submit button "_eventId_submit" indicates the event id to use for deciding - where to transition to next. Given an event with id of "submit" the "selectFile" view transitions - to the "uploadFile" state: - -<action-state id="uploadFile"> - <action bean="uploadAction"/> - <transition on="success" to="selectFile"> - <set attribute="fileUploaded" scope="flash" value="true"/> - </transition> - <transition on="error" to="selectFile"/> -</action-state> - - - - The "uploadFile" state is an action state. Action states integrate with business application code and - respond to the execution of that code by deciding what state of the flow to enter next. The code for the - uploadFile state is in the "uploadAction" bean declared in the Spring web context (/WEB-INF/fileupload-servlet.xml): - -<bean id="uploadAction" class="org.springframework.webflow.samples.fileupload.FileUploadAction" /> - - FileUploadAction has simple logic. It picks one of two Web Flow defined events - success or error, - depending on whether the uploaded file size is greater than 0 or not. Both success and error - transition back to the "selectFile" view state. However, a success event causes an attribute named - "fileUploaded" to be set in flash scope - - - A flash-scoped attribute called "file" is also set programmatically in the FileUploadAction bean: - -context.getFlashScope().put("file", new String(file.getBytes())); -return success(); - - This illustrates the choice to save attributes in one of several scopes either programatically or - declaratively. - - - - - Birthdate Example - - Overview - - Birthdate is a web application with 3 consequitive screens. The first two collect user input - to populate a form object. The third presents the results of business calculations based on - input provided in the first two screens. - - - Birthdate demonstrates Spring Web Flow's Struts integration as well as the use of FormAction, - a multi-action used to do the processing required for all three screens. The sample also uses JSTL - taglibs in conjunction with flows. - - - - Web.xml - - The web.xml configuration maps requests for "*.do" to a regular Struts ActionServlet: - -<servlet> - <servlet-name>action</servlet-name> - <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> -</servlet> - -<servlet-mapping> - <servlet-name>action</servlet-name> - <url-pattern>*.do</url-pattern> -</servlet-mapping> - - The web.xml also sets up the loading of a Spring context at web application startup: - -<context-param> - <param-name>contextConfigLocation</param-name> - <param-value> - /WEB-INF/webflow-config.xml - </param-value> -</context-param> - -<listener> - <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> -</listener> - - The Spring web context contains beans to set up the Web Flow runtime environment. As will be - shown in the next section Struts is configured with a Web Flow action that relies on the - presence of a flowExecutor and a flowRegistry beans in this context. - - - - Struts Configuration - - The Struts configuration (WEB-INF/struts-config.xml) defines the following action mapping: - -<action-mappings> - <action path="/flowAction" name="actionForm" scope="request" - type="org.springframework.webflow.executor.struts.FlowAction"/> -</action-mappings> - - FlowAction is a Struts action acting as a front controller to the Web Flow system routing Struts - requests to one or more managed web flow executions. To fully configure the FlowAction a Spring - web context is required to define flowExecutor and flowRegistry beans (named exactly so). This is - an excerpt from the Spring web context (/WEB-INF/webflow-config.xml) defining these beans: - -<!-- 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/birthdate.xml"/> - <flow:location path="/WEB-INF/birthdate-alternate.xml"/> -</flow:registry> - - - - Based on the above, Web Flow is configured with two flows - birthdate and birthdate-alternate, - which can be invoked as follows: - -/swf-birthdate/flowAction.do?_flowId=birthdate -/swf-birthdate/flowAction.do?_flowId=birthdate-alternate - - The Struts configuration file also defines several global forwards: birthdateForm, cardForm, - and yourAge, which will be referenced from Web Flow definitions as logical view names - (and left to Struts to resolve to actual JSP pages). In general Web Flow does not aim to replace - view resolution capabilities of web frameworks such as Struts or Spring MVC. - It focuses on the C in MVC. - - - - Birthdate Web Flow - - The birthdate web flow (WEB-INF/birthdate.xml) defines the following start state: - -<view-state id="enterBirthdate" view="birthdateForm"> - <render-actions> - <action bean="formAction" method="setupForm" /> - </render-actions> - <transition on="submit" to="processBirthdateFormSubmit" /> -</view-state> - - The setupForm action is called to perform initializations for the enterBirthdate view state. - Its action bean is defined the Spring web context WEB-INF/webflow-config.xml: - -<bean id="formAction" class="org.springframework.webflow.samples.birthdate.BirthDateFormAction" /> - - BirthDateFormAction is a FormAction - it extends Web Flow's FormAction class, which serves a - purpose similar to that of Spring MVC's SimpleFormController providing common form functionality - for data binding and validation. - - - When the BirthDateFormAction bean is instantiated it sets the name, class and scope of the form - object to use for loading form data upon display and collecting form data upon submit: - -public BirthDateFormAction() { - // tell the superclass about the form object and validator we want to - // use you could also do this in the application context XML ofcourse - setFormObjectName("birthDate"); - setFormObjectClass(BirthDate.class); - setFormObjectScope(ScopeType.FLOW); - setValidator(new BirthDateValidator()); -} - - The form object "birthDate" is placed in flow scope, which means it will not be re-created with - each request but will be obtained from flow scope instead as long as the request remains within - the same flow. - - - Once setupForm is done, the "birthdateForm" view will be rendered. - The logical view name "birthdateForm" is a global-forward in struts-config.xml resolving to - /WEB-INF/jsp/birthdateForm.jsp. This JSP collects data for the fields "name" and "date" bound to - the birthDate form object and posts back to FlowAction with a submit image named - "_eventId_submit". An event with the id of "submit" causes a transition to the - processBirthdateFormSubmit action state defined as follows: - -<action-state id="processBirthdateFormSubmit"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validateBirthdateForm" /> - </action> - <transition on="success" to="enterCardInformation" /> - <transition on="error" to="enterBirthdate" /> -</action-state> - - The processBirthDateFormSubmit action state uses the same formAction bean as the one already used - to setup the form. This time its bindAndValidate - method is used to populate and validate the html form values. Also, note the "validateMethod" - attribute used to specify the name of the method to invoke on the Validator object setup in the - constructor of the BirthDateFormAction. The use of this attribute allows partial validation of - complex objects populated over several consecutive screens. - - - On error the action returns to the view state it came from. On success it transitions to the - enterCardInformation view state: - -<view-state id="enterCardInformation" view="cardForm"> - <transition on="submit" to="processCardFormSubmit" /> -</view-state> - - The logical view name "cardForm" is a global-forward in struts-config.xml resolving to - /WEB-INF/jsp/cardForm.jsp. This JSP collects data for the remaining fields of the birthDate form - object - "sendCard" and "emailAddress", and posts back to FlowAction with a submit image named - "_eventId_submit". An event with the id of "submit" causes a transition to the - processCardFormSubmit action state defined as follows: - -<action-state id="processCardFormSubmit"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validateCardForm" /> - </action> - <transition on="success" to="calculateAge" /> - <transition on="error" to="enterCardInformation" /> -</action-state> - - For this action state the bindAndValidate method of the formAction bean is used to populate and - validate the remaining html form values. The "validateMethod" attribute specifies the name of the - method to invoke on the Validator object specific to the fields loaded on the current screen. - - - On error the action returns to the view state it came from. On success it transitions to another - action state called calculateAge: - -<action-state id="calculateAge"> - <action bean="formAction" method="calculateAge" /> - <transition on="success" to="displayAge" /> -</action-state> - - The logic for the calculateAge action state is in the calculateAge method of the same formAction - bean used for data binding and validation. This demonstrates the flexibility Web Flow allows in - properly structuring control and business logic according to function. - - - The caculateAge method performs business calculations and adds a string in request scope with the - calculated age. Upon successful completion the calculateAge action state transitions to the end - view state: - -<end-state id="displayAge" view="yourAge" /> - - Once again the logical view name "yourAge" is a global-forward in struts-config.xml resolving to - /WEB-INF/jsp/yourAge.jsp. This JSP page retrieves the calculated age from request scope and - displays the results for the user. - - - The transition to the end state indicates the end of the web flow. The flow execution is cleaned up. - If the web flow is entered again a new flow execution will start, creating a new form - object named "birthDate" and placing it in flow scope. - - - - Birthdate-alternate Web Flow - - The birthdate-alternate web flow (/WEB-INF/birthdate-alternate.xml) offers an alternative way and - more compact way of defining the same web flow. For example the birthdate web flow defines two - independent states for the first screen - a view state (enterBirthdate) and an action state - (processBirthdateFormSubmit). In birthdate-alternate those are encapsulated in the view state - enterBirthdate as follows: - -<view-state id="enterBirthdate" view="birthdateForm"> - <render-actions> - <action bean="formAction" method="setupForm" /> - </render-actions> - <transition on="submit" to="enterCardInformation"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validateBirthdateForm" /> - </action> - </transition> -</view-state> - - Here the setupForm action state is defined as a render-action of the enterBirthdate view state - while the transition to the next screen uses a nested action bean invoked before the transition - occurs. Notice that success is implicitly required for the transition to occur. Similarly on error - the transition does not occur and the same view state is displayed again. - - - The second screen is also defined with a nested transition and action bean: - -<view-state id="enterCardInformation" view="cardForm"> - <transition on="submit" to="calculateAge"> - <action bean="formAction" method="bindAndValidate"> - <attribute name="validatorMethod" value="validateCardForm" /> - </action> - </transition> -</view-state> - - The remaining two states - calculateAge and displayAge are identical. - - - - - Phonebook-Portlet Example - - Overview - - The Phonebook-Portlet demonstrates how to run the - Phonebook - sample as a JSR-168 portlet. The functionality for Phonebook and Phonebook-Portlet - including web flow definitions, JSP pages, and Java classes is the same and - already well documented. - The focus in Phonebook-Portlet is specifically on how to configure - and run Phonebook in a Portal container. - - - - JSR-168 defines portlets but not how portlets integrate into a - portal container. This process is left open to portal vendors who - have their own individual mechanisms. - The Phonebook-Portlet sample is configured to run with - Apache Pluto - - a reference implementation of the Java Portlet Specification. - However, its dependence on Pluto is limited to configuration in web.xml. - Hence it should be easy to adapt for use - in other Portal/Portlet implementations after learning the - deployment steps specific for that implementation. - - - - - Portal/Portlet Related Software Used in the Sample - - This section provides a very brief introduction to the portal related - supporting software used in the sample - namely Apache Pluto - and the Portlet MVC framework. If this is not new for you - feel free to skip to the next section. - - - Apache Pluto - - For those familiar with servlet applications the process - of deploying and running a portlet application can be - confusing and requires some explanation. - Typically an application with JSR-168 portlets runs in - one webapp while a portal/portlet container runs - in a separate webapp making cross-context calls to - portlets. How exactly this is configured - depends on each portal vendor. - - - Pluto is an open-source reference implementation of the - Java Portlet specification. The following general steps - are required to run portlets with it. First the - the portlet application's web.xml is "injected" with - configuration required for Pluto. Secondly Pluto's - Portal web application, usually set to run at - http://localhost:8080/pluto/portal - is used to add or remove portlets to one or more - portal container pages. - - - The web.xml for the Phonebook-Portlet sample has - already been "injected" with the configuration required - for Pluto 1.1.0. Although this enables it for use with Pluto - you must still use the - admin pages of Pluto's Portal web application to add - the Phonebook-Portlet to a test portal page. For more - information on how to do this please follow instructions from - Apache Pluto. - - - - Portlet MVC Framework - - The Portlet MVC framework represents Spring's support for JSR-168. - It has many parallels with the Spring MVC framework such - as the DispatcherPortlet, the Controller interface, - handler mappings, view resolvers, and exception handlers. - The main differences between Portlet MVC and Spring MVC - have to do with the lifecycles of a portlet and its - distinct phases as defined in the Porlet Specification: - the action and the render phases. - For more information see - - Chapter 16 (Portlet MVC Framework) from the Spring reference - documentation. - - - - Getting Phonebook Portlet up and Runnign with Apache Pluto - - Since the phonebook portlet was tested with Apache Pluto we've - decided to documents the steps taken to deploy and run it - - Download the Pluto 1.1 binary distribution named pluto-current-bundle from http://portals.apache.org/pluto - Unzip the binary distribution to any directory. - Create the directory [pluto-home]/webapps/swf-phonebook-portlet - Copy the content of [webflow-release]/spring-webflow-samples/phonebook-portlet/target/artifacts/war-expanded to the directory created in the previous step - Start Pluto with [pluto-home]/bin/startup - Go to http://localhost:8080/pluto/portal - Login as tomcat/tomcat (or any other user but see note below) - After logging in you will be taken to the Portal Test page. - Here you will see a Navigation pull-down menu at the top. Select 'Pluto Admin' from it to go to the Pluto Admin page. - On the Pluto Admin page under Portlet Applications you will see a drop-down with available portlet applications - Select '/swf-phonebook-portlet' from it, then phonebook from the drop-down next to it, and then press the 'Add Portlet' button - Use the Navigation menu at the top to go back to the Test Page. The Phonebook portlet should be present. - - - - - The tomcat user must have the 'pluto' role. Open - [pluto-home]/conf/tomcat-users.xml and ensure the - following lines are there: - -<role rolename="pluto"/> -<user username="tomcat" password="tomcat" roles="tomcat,pluto"/> - - - - - - - Portlet.xml Configuration - - Portlet.xml is a standard deployment descriptor where - portlet resources are defined. The Phonebook-Portlet - is based the Portlet MVC DispatcherPorlet: - -<portlet-class> - org.springframework.web.portlet.DispatcherPortlet -</portlet-class> - - The DispatcherPortlet is Spring's implementation of the Portlet interface - dispatching requests for a portlet to registered Portlet MVC handlers. - The phonebook portlet is configured with the following Spring - contexts containing Portlet MVC handler, controller and - view resolver beans: - -<init-param> - <name>contextConfigLocation</name> - <value> - /WEB-INF/phonebook-portlet-config.xml /WEB-INF/phonebook-webflow-config.xml - </value> -</init-param> - - The above configuration defines phonebook as a portlet resource. In order - to use it in a portal/portlet container - additional web.xml configuration is required. - - - - Web.xml Configuration - - The Java Portlet Specification is defined as a layer over existing Servlet - infrastructure. Therefore some sort of a servlet is required to accept servlet - requests and expose portlet resources. Portal vendors - provide such servlets and specific configuration varies by vendor. - The Phonebook-Portlet has the following Apache Pluto servlet definition - and servlet mapping: - -<!-- Generated Portlet Wrapper Servlet for Apache Pluto deployment --> -<servlet> - <servlet-name>phonebook</servlet-name> - <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class> - <init-param> - <param-name>portlet-name</param-name> - <param-value>phonebook</param-value> - </init-param> - <load-on-startup>1</load-on-startup> -</servlet> -<servlet-mapping> - <servlet-name>phonebook</servlet-name> - <url-pattern>/PlutoInvoker/phonebook</url-pattern> -</servlet-mapping> - - - - - The above configuration was auto generated using ant tasks from - Apache Pluto 1.1.0. This configuration is included in web.xml - for convenience and also as an example. - For the most up-to-date information on required configuration please - check Pluto's documentation. - - - - The web.xml configuration also contains the following servlet definition: - -<servlet> - <servlet-name>viewRendererServlet</servlet-name> - <servlet-class> - org.springframework.web.servlet.ViewRendererServlet - </servlet-class> -</servlet> -<servlet-mapping> - <servlet-name>viewRendererServlet</servlet-name> - <url-pattern>/WEB-INF/servlet/view</url-pattern> -</servlet-mapping> - - - - The main purpose of this servlet is to allow reuse of Spring MVC's flexible - view resolution and rendering capabilities in a Portlet application. - The DispatcherPortlet converts a PortletRequest/PortletResponse to an - HttpServletRequest/HttpServletResponse and then performs an include of - this servlet. - - - - Portlet MVC Configuration - - The phonebook-portlet-config.xml is very similar to the Spring MVC - equivalent phonebook-servlet.xml from the Phonebook sample. The main - difference is in the use of a PortletModeHandlerMapping: - -<bean id="portletModeControllerMapping" - class="org.springframework.web.portlet.handler.PortletModeHandlerMapping"> - <property name="portletModeMap"> - <map> - <entry key="view" value-ref="flowController"/> - </map> - </property> -</bean> - - and a PortletFlowController: - -<bean id="flowController" class="org.springframework.webflow.executor.mvc.PortletFlowController"> - <property name="flowExecutor" ref="flowExecutor"/> - <property name="defaultFlowId" value="search-flow"/> -</bean> - - A PortletModeHandlerMapping allows mapping specific to each - portlet mode. The VIEW mode in this case is mapped to the - flowController bean, which delegates the request to Web Flow's - executor for launching or resuming a flow from a flow definition. - For more information on Phonebook flow definitions please - refer to the - Phonebook - sample documentation. - - - One last thing to observe is the following configuration in - /WEB-INF/phonebook-webflow-config.xml: - -<!-- Launches new flow executions and resumes existing executions. --> -<flow:executor id="flowExecutor" registry-ref="flowRegistry"> - <flow:execution-attributes> - <!-- execution redirects don't apply in a Portlet environment --> - <flow:alwaysRedirectOnPause value="false"/> - </flow:execution-attributes> -</flow:executor> - - As the comment indicates the default behavior of redirect after submit - must be turned off in a portlet environment where there is no HTTP redirect. - For more information on the alwaysRedirectOnPause refer to the following - article. - - - - diff --git a/spring-webflow/docs/reference/src/spring-faces.xml b/spring-webflow/docs/reference/src/spring-faces.xml deleted file mode 100644 index fae2b26c..00000000 --- a/spring-webflow/docs/reference/src/spring-faces.xml +++ /dev/null @@ -1,382 +0,0 @@ - - - Spring Faces - - Introduction - - Spring Faces is the home of the new Spring Web Flow + JSF 1.2 integration layer, as well as a number of additional value adds specific - to a JSF environment. These value adds include: - - - Unified EL Integration - A separate implementation of the ExpressionParser from Spring Binding that uses - the new Unified EL from JSF 1.2 and JSP 2.1. This allows for JSF users to use the same expression language in their flow definitions - as in their JSF views. - - - Client Side Validator Components - A small set of JSF components that work as "advisors" on regular JSF inputText components. These - components make use of the rich validation capabilities of the Dojo javascript framework by default, with an alternate set of tags - based on Ext also available. - - - - Web Flow Java Server Faces (JSF) integration - - The Spring Faces module provides strong integration between Spring Web Flow and Java Server Faces (JSF). When used with JSF, - Spring Web Flow takes responsibility for view navigation handling and managing model state, adding power and - simplicity beyond JSF's default navigation system and object scopes. Plain JSF views and components continue to work just as before, - and are able to participate in flows with full access to flow state. In addition, other view technologies - such as Facelets continue to plug-in normally. - - - The JSF integration relies on custom implementations of core JSF artifacts to drive the execution of flows. In addition, - it relies on custom ELResolvers to access flow execution attributes from JSF components. - - - Adding Spring Web Flow extensions to a JSF application. - - Using Spring Web Flow in a JSF environment does not require any additions to the application's faces-config.xml. The Spring Faces - jar just needs to be on the classpath and all of the custom JSF artifacts provided by spring-faces will be picked - up by JSF automatically. Ideally, when building new applications from the start with Spring Faces, a faces-config.xml should - not be needed at all in preference for having all beans managed by Spring. - - - - Configuring the Web Flow system - - The artifacts configured by Spring Faces use Spring to access the Web Flow system configuration. - This requires the Spring Web Servlet to be configured in the web.xml deployment descriptor: - - -<!-- The front controller of the Spring Web application, responsible for handling all application requests --> -<servlet> - <servlet-name>Spring Web Servlet</servlet-name> - <servlet-class>org.springframework.webflow.servlet.SpringWebServlet</servlet-class> - <init-param> - <param-name>configLocations</param-name> - <param-value>/WEB-INF/config/web-application-config.xml</param-value> - </init-param> - <load-on-startup>1</load-on-startup> -</servlet> - -<!-- Map all /spring/* requests to the Spring Web Servlet for handling --> -<servlet-mapping> - <servlet-name>Spring Web Servlet</servlet-name> - <url-pattern>/spring/*</url-pattern> -</servlet-mapping> - - - The application context bootstrapped by the Spring Web Servlet should contain the Web Flow system configuration. - The example webflow-config.xml below shows a typical Web Flow configuration for a JSF environment: - - -<?xml version="1.0" encoding="UTF-8"?> -<beans xmlns="http://www.springframework.org/schema/beans" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns:web="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-2.0.xsd"> - - <!-- Imports the "application-layer" definining business logic and data access services --> - <import resource="application-layer-config.xml"/> - - <web:flow-executor id="flowExecutor" flow-registry="flowRegistry"> - <web:flow-execution-listeners> - <web:listener ref="jpaFlowExecutionListener" criteria="*"/> - </web:flow-execution-listeners> - </web:flow-executor> - - <web:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"> - <web:flow-location path="flow/main/main.xml" /> - <web:flow-location path="flow/booking/booking.xml" /> - <web:flow-builder class="org.springframework.faces.ui.resource.ResourcesFlowBuilder" /> - </web:flow-registry> - - <bean id="flowBuilderServices" class="org.springframework.webflow.engine.builder.support.FlowBuilderServices"> - <property name="expressionParser"> - <bean class="org.springframework.webflow.core.expression.el.WebFlowELExpressionParser"> - <constructor-arg > - <bean class="org.jboss.el.ExpressionFactoryImpl"/> - </constructor-arg> - </bean> - </property> - <property name="viewFactoryCreator"> - <bean class="org.springframework.faces.webflow.JsfViewFactoryCreator"/> - </property> - </bean> - -</beans> - - - A bean named flowExecutor must be configured and linked with a flow definition registry - that contains the flows eligible for execution. Note the flowExecutor bean name is significant, - as that is bean name the Web Flow JSF extensions will expect. - - - Any flow executor property such as the flow execution repository type is configurable here, consistent - with the other environments Spring Web Flow supports. - - - The flowRegistry bean definition shows the registration of two XML based flow definitions, as well - as a special java-based FlowBuilder that installs a special flow for serving the javascript and CSS resources needed - by the Spring Faces custom JSF components. - - - The flowBuilderServices provides a number of JSF-specific services to the flowRegistry, including the - WebFlowELExpressionParser that allows Web Flow to use the Unified EL for parsing expressions in flow definitions. - - - - Configuring the FacesServlet - - Even in an ideal scenario where the SpringWebServlet is handling all incoming requests, the FacesServlet - must still be configured in web.xml in order for JSF to bootstrap properly: - - -<!-- Here so the JSF implementation can initialize, not used at runtime --> -<servlet> - <servlet-name>Faces Servlet</servlet-name> - <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> - <load-on-startup>1</load-on-startup> -</servlet> - -<!-- Mapping for faces initialization --> -<servlet-mapping> - <servlet-name>Faces Servlet</servlet-name> - <url-pattern>*.faces</url-pattern> -</servlet-mapping> - - - This configuration also allows for the mixing of legacy pure JSF request handling with the request handling of Spring Web Flow for easier - page-by-page migration. - - - - Launching a flow execution - normal HTML anchor - - The preferred way of launching a flow from an external system, such as a normal JSF view is by accessing flow definition - URLs directly using a bookmark or normal HTML link: - - -<a href="/spring/main">Go</a> - - - This link would launch the "main" flow, assuming /spring/* has been mapped to the SpringWebServlet defined within web.xml. - - - - Launching a flow execution - JSF command link component - - Before going this route, it should be considered whether the same effect can be achieved with a normal REST-ful URL link in combination perhaps - in combination with a custom Web Flow action in order to execute specialized logic. If it is an absolute requirement to use - a JSF UICommand component, then the recommended approach is to programmatically have JSF forward the request to the flow execution URL from within - a JSF ActionListener. - - -public void myActionListener(ActionEvent event) { - // Execute any required processing and then forward to the flow execution - - facesContext.getCurrentInstance().getExternalContext().dispatch("/spring/main/"); - facesContext.getCurrentInstance().responseComplete(); -} - - - - Flow definitions in a JSF environment - - Flow definitions in a JSF environment are just plain Spring Web Flow definitions: - - -<?xml version="1.0" encoding="UTF-8"?> -<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-1.0.xsd"> - - <var name="myBean" class="example.ManagedBeanImpl" scope="conversation" /> - - <start-state idref="displayView" /> - - <view-state id="displayView" view="myview.jsp"> - <transition on="submit" to="prepareNextView"/> - </view-state> - - <action-state id="prepareNextView" > - <bean-action bean="myService" method="loadMyModel"> - <method-arguments> - <argument expression="#{myBean.foo}"/> - </method-arguments> - </bean-action> - <transition on="success" to="displayNextView"/> - </action-state> - - <view-state id="displayNextView" view="mynextview.jsp" /> - -</flow> - - - A primary benefit of using JSF is it is a rich UI component framework, and UI components have both data and behavior. - As JSF components typically handle data binding and field-level validation behaviors, the actual flow - definition logic is often simpler and more focused as a result. - - - An important difference to note in the above example is the difference in using EL expressions versus Web Flow's traditional - OGNL expressions. When using the ELExpressionParser, the chain of configured resolvers will automatically resolve an expression - against the correct scope, so the "conversationScope" identifier is optional in the expression when referencing "myBean". - - - Views selected by view states are specified using paths relative to the current flow definition. In the above example, it is - expected that myview.jsp and mynextview.jsp are both located in the same directory as the flow definition. - - - - Resuming a flow execution - form bound to flow execution variables - - Views participating in flows are just plain JSF views. They may also incorporate other - JSF view technologies such as Facelets and Ajax4JSF. - - -<f:view> - <h:form id="form"> - ... - <h:inputText id="propertyName" value="#{someBean.someProperty}"/> - ... - <h:commandButton type="submit" value="Next" action="submit"/> - </h:form> -</f:view> - - - As shown above, there is nothing Spring Web Flow specific here. The flow execution - key is automatically tracked by a special UI component in the view root, so there is no need to - track it manually. Action outcomes are automatically mapped to Spring Web Flow event identifiers - signaled against the current state. - - - - Spring Faces JSF Components - - Spring Faces provides some lightweight JSF components that act in an "advisor" role to provide rich client-side validation - capabilities to standard inputText components. These can be used in place of server-side JSF validators to provide immediate - validation feedback to the end user without the overhead of another fine-grained call to the server. The default implementation - of these components use the Dojo javascript library to provide this validation behavior. Dojo was chosen due to their increased - attention to accessibility concerns compared to other javascript frameworks. An alternate implementation based on the Ext library - is also provided. Though Ext does not address accessibility issues, it can still be attractive for use in internal corporate - intranet style applications. - - - Spring Faces Component Configuration - - The Spring Faces components are currently provided as Facelets tags. In order to utilize them, the - following namespace declaration must be added to the header of a Facelets view template: - - -xmlns:sf="http://www.springframework.org/tags/faces" - - - - Spring Faces Resource Loading - - Spring Faces requires the installation of a special flow for loading javascript and CSS resources, as shown in the configuration - example. This special stateless flow serves up resources corresponding to URLs such as "/spring/resources/dojo/dojo.js". This flow - searches for the corresponding resource as follows: - - - 1) Look for the resource in the web app root using the context-relative path "/dojo/dojo.js", and serve the resource if found. - - - 2) If not found in the web app root, try and load the resource from the classpath using the path "/META-INF/dojo/dojo.js" and - serve the resource if found. - - - - - For convenience, the external javascript libraries that the Spring Faces components depend on are made available in seperate - jar files, and will be automatically loaded by the components when needed using the proper resource URLs. Since the resource loading - mechanism checks in the web app classpath first it is possible to, for example, override the provided resources with a custom build of the - Dojo or Ext library that is optimized for the particular application. - - - - Using The Spring Faces Client Side Validation Components - - Spring Faces provides three different client-side validator components: - - - - - - <sf:clientTextValidator> - Provides validation with customizable error messages for text fields. - - - - - <sf:clientNumberValidator> - Provides validation and input filtering with customizable error messages for numeric - fields. - - - - - <sf:clientDateValidator> - Provides validation and a rich popup date picker control with customizable error - messages for date fields. - - - - - <sf:validateAllOnClick> - When wrapped around a UICommand component such as <h:commandButton> or <h:commandLink> - fires all client-side validators when the UICommand component is clicked and prevents the form from being submitted if - any of the validations fail. - - - - - - The validator components must be wrapped around an <h:inputText> component (or any other component that renders an HTML text input). - For example, see the following snippet from the Booking sample application: - - - -<sf:clientDateValidator required="true"> - <h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true"> - <f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/> - </h:inputText> -</sf:clientDateValidator> - - - - In general, each of the available validations has a corresponding sensible default error message. The error messages - can be overridden via the component's "invalidMessage" attribute. All of the customizable message attributes are - value-binding aware so that expressions may be used to bind to keys in the application message bundle if so desired. - - - Please refer to the javadocs of the component classes to see all of the attributes for the components. More - extensive taglib docs will be available with the final release of Spring Web Flow 2.0. - - - - Using Ext Version of The Spring Faces Client Side Validation Components - - An alternate version of the components based on the Ext library is provided under a separate tag namespace. - In order to utilize them, the following namespace declaration must be added to the header of a Facelets view template: - - -xmlns:sfe="http://www.springframework.org/tags/faces-ext" - - - The basic behavior of the Ext versions of the components is the same, but the tags have different attributes that correspond with the attributes - of the underlying Ext widgets. Please refer to the javadocs of the component classes to see all of the attributes for the components. More - extensive taglib docs will be available with the final release of Spring Web Flow 2.0. - - - - - Spring Web Flow JSF Integration Samples - - See the booking-jsf sample that provides a complete example of Spring Web Flow - operating in a JSF environment, including use of flow-managed persistence, EL integration, and the - client-side JSF validator components of Spring Faces. - - - - \ No newline at end of file