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 FlowReference Documentation
- Version 2.0-m4
+ Version 2.0 M4March 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