reference manual updates

This commit is contained in:
Keith Donald
2008-03-10 03:32:14 +00:00
parent 456db3082d
commit 8f0e8daca0
31 changed files with 87 additions and 6807 deletions

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="defining-flows">
<title>Defining Flows</title>
<sect1 id="introduction">
<title>Introduction</title>
<para>
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.
</para>
</sect1>
<sect1 id="flow-overview">
<title>What is a Flow?</title>
<para>
A flow encapsulates a reusable sequence of steps that can execute in different contexts.
Below is a <ulink url="http://www.jjg.net/ia/visvocab/">Garrett Information Architecture</ulink> diagram illustrating a reference to a flow that encapsulates the steps of a hotel booking process:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/hotels-site.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/hotels-site.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>A BookHotel Flow Definition</para>
</caption>
</mediaobject>
</sect1>
<sect1 id="flow-makeup">
<title>What is the makeup of a typical Flow?</title>
<para>
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.
</para>
<para>
The example below shows the structure of the book hotel flow referenced in the previous diagram:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/hotels-site-bookhotel-flow.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/hotels-site-bookhotel-flow.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Hotels Site Diagram that references a "Book Hotel" flow</para>
</caption>
</mediaobject>
</sect1>
<sect1 id="flow-definition">
<title>How are Flows authored?</title>
<para>
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.
</para>
</sect1>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@@ -1,247 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="flow-execution-repository">
<title>Flow execution repositories</title>
<sect1 id="repository-intro">
<title>Introduction</title>
<para>
A flow execution represents an executing flow <emphasis>at a point in time</emphasis>.
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).
</para>
<para>
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.
</para>
<para>
The problem of flow execution persistence is addressed by Spring Web Flow's <emphasis>flow
execution repository subsystem</emphasis>. In this chapter, you will learn how to use the system
to manage the storage of active web conversations in a stable manner.
</para>
</sect1>
<sect1 id="repository-architecture-overview">
<title>Repository architecture overview</title>
<para>
Recall the following bullet points noting what happens when a flow execution enters a ViewState:
</para>
<para>
<orderedlist>
<listitem>
<para>
When a flow execution reaches a <literal>ViewState</literal> it is said to have <emphasis>paused</emphasis>,
where it waits in that state for user input to be provided so it can continue. After pausing, the
<literal>ViewSelection</literal> returned is used to issue a response to the user
that provides a vehicle for collecting the required user input.
</para>
</listitem>
<listitem>
<para>
User input is provided by <emphasis>signaling an event</emphasis> that
<emphasis>resumes</emphasis> the flow execution in the paused view state.
The input event communicates what user action was taken.
</para>
</listitem>
</orderedlist>
</para>
<para>
Each time an active flow execution is <emphasis>paused</emphasis>, it is saved out to a
repository. When the next request comes in for that flow execution, it is restored
from the repository, <emphasis>resumed</emphasis>, and continued. This process continues
until the flow execution reaches an end state, at which time it is removed from the repository.
</para>
<para>
This process is demonstrated over the next two graphics:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecution-persistence.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecution-persistence.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Request one (1) - Paused flow execution persistence</para>
</caption>
</mediaobject>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecution-restoration.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecution-restoration.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Request two (2) - Paused flow execution restoration, removal on end</para>
</caption>
</mediaobject>
</sect1>
<sect1 id="repository-entry-identity">
<title>Flow execution identity</title>
<para>
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 <emphasis>persistent identifer</emphasis> 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.
</para>
<sect2 id="conversationId">
<title>Conversation identifier</title>
<para>
The first part of a flow execution's persistent identity is a
unique <emphasis>conversation identifier</emphasis>. This serves as an index into
the <emphasis>logical</emphasis> conversation between the browser and the server that
has just started.
</para>
</sect2>
<sect2 id="continuationId">
<title>Continuation identifier</title>
<para>
The second part of a flow execution's persistent identity is a <emphasis>continuation identifier</emphasis>.
This identifier serves as an index into a flow execution representing the state of the conversation
<emphasis>at this point in time</emphasis>.
</para>
</sect2>
<sect2 id="flowExecutionKey">
<title>Flow execution key</title>
<para>
Together the conversation id plus the continuation id make up the unique two-part
<emphasis>flow execution key</emphasis> that identifies a state
of a conversation <emphasis>at a point in time</emphasis>. By submitting this key
in a subsequent request, a browser can restore the conversation at that point
and <emphasis>continue</emphasis> from there.
</para>
<para>
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 <emphasis>conversation identifier</emphasis>, as the same logical
conversation is in progress; however the <emphasis>continuation identifier</emphasis>
changes to provide an index into the state of the flow execution
at <emphasis>this new point in time</emphasis>.
</para>
<para>
By submitting this new key in a subsequent request, a browser can
restore the conversation at that point and <emphasis>continue</emphasis> from there.
This process continues until a flow execution reaches an end state during event processing
signaling the end of the conversation.
</para>
</sect2>
</sect1>
<sect1 id="conversation-ending">
<title>Conversation ending</title>
<para>
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 <emphasis>ended</emphasis>,
resulting in any flow execution continuations associated with the conversation being purged.
</para>
<para>
Once a conversation has ended, the conversation identifier is no longer valid
and can never be used again.
</para>
</sect1>
<sect1 id="repository-implementations">
<title>Flow execution repository implementations</title>
<para>
The next section looks at the repository implementations that are available for use
with Spring Web Flow out-of-the-box.
</para>
<sect2 id="repository-simple">
<title>Simple flow execution repository</title>
<para>
The simplest possible repository (<literal>SimpleFlowExecutionRepository</literal>).
This repository stores <emphasis>exactly one</emphasis> 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.
</para>
<note>
<para>
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.
</para>
</note>
<note>
<para>
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.
</para>
</note>
</sect2>
<sect2 id="repository-continuation">
<title>Continuation flow execution repository</title>
<para>
This repository (<literal>ContinuationFlowExecutionRepository</literal>) stores <emphasis>one to many</emphasis> 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.
</para>
<note>
<para>
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.
</para>
</note>
<para>
Like the simple implementation, this repository implementation provides support for <emphasis>conversation
invalidation after completion</emphasis> 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.
</para>
<para>
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.
</para>
</sect2>
<sect2 id="repository-client">
<title>Client continuation flow execution repository</title>
<para>
This repository is entirely stateless and its use entails no server-side state
(<literal>ClientContinuationFlowExecutionRepository</literal>).
</para>
<para>
This is achieved by encoding a serialized flow execution directly into the
flow execution continuation key that is sent in the response.
</para>
<para>
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.
</para>
<note>
<para>
This repository implementation does not currently support
<emphasis>conversation invalidation after completion</emphasis>, as
this capability requires tracking active conversations using some
form of centralized storage, like a database table.
</para>
</note>
<note>
<para>
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.
</para>
</note>
</sect2>
</sect1>
</chapter>

View File

@@ -1,673 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="flow-execution">
<title>Flow execution</title>
<sect1 id="execution-intro">
<title>Introduction</title>
<para>
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.
</para>
<para>
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.
</para>
</sect1>
<sect1 id="execution">
<title>FlowExecution</title>
<para>
A <literal>org.springframework.webflow.execution.FlowExecution</literal> is a runtime instantiation of a flow definition.
Given a single <literal>FlowDefinition</literal>, any
number of independent flow executions may be created.
These executions are typically created by a <literal>FlowExecutionFactory</literal>.
</para>
<para>
A flow execution carries out the execution of program instructions defined within
its definition in response to user events.
</para>
<para>
<emphasis>
It may be helpful to think of a flow definition as analagous to a Java <literal>Class</literal>, and a
flow execution as analagous to an object instance of that <literal>Class</literal>. Signaling
an execution event can be considered analagous to sending an object a message.
</emphasis>
</para>
<sect2 id="execution-creation">
<title>Flow execution creation</title>
<programlisting>
FlowDefinition definition = ...
FlowExecutionFactory factory = ...
FlowExecution execution = factory.createFlowExecution(definition);
</programlisting>
<para>
Once created, a new flow execution is initially inactive, waiting to be started. Once
started, a flow execution becomes active by entering its <literal>startState</literal>.
From there, it continues executing until it enters a state where user input is required
to continue or it terminates.
</para>
</sect2>
<sect2 id="execution-start">
<title>Flow execution startup</title>
<programlisting>
ExternalContext context = ...
execution.start(context);
</programlisting>
<para>
When a flow execution reaches a state where input is required to continue, it is said to have <emphasis>paused</emphasis>,
where it waits in that state for user input to be provided.
</para>
<para>
User input is provided by <emphasis>signaling an event</emphasis> that
<emphasis>resumes</emphasis> 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.
</para>
<para>
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.
</para>
</sect2>
<sect2 id="execution-resume">
<title>Flow execution resume</title>
<programlisting>
ExternalContext context = ...
execution.resume(context);
if (execution.isActive()) {
// still active but paused
} else {
// has ended
}
</programlisting>
</sect2>
<sect2 id="execution-lifecycle">
<title>Flow execution lifecycle</title>
<para>
As outlined, a flow execution can go through a number of phases throughout its lifecycle;
for example, <emphasis>created</emphasis>, <emphasis>active</emphasis>, <emphasis>paused</emphasis>,
<emphasis>ended</emphasis>.
</para>
<para>
Spring Web Flow gives you the ability to observe the lifecycle of an
executing flow by implementing a <literal>FlowExecutionListener</literal>.
</para>
<para>
The different phases of a flow execution are shown graphically below:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecution-statediagram.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecution-statediagram.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Flow execution lifecycle</para>
</caption>
</mediaobject>
</sect2>
<sect2 id="execution-properties">
<title>Flow execution properties</title>
<para>
The Spring Web Flow flow execution implementation is <literal>org.springframework.webflow.engine.impl.FlowExecutionImpl</literal>,
typically created by a <literal>FlowExecutionImplFactory</literal> (a <literal>FlowExecutionFactory</literal> implementation).
The configurable properties of this flow execution implementation are summarized below:
</para>
<table>
<title>Flow Execution properties</title>
<tgroup cols="4">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Property name</entry>
<entry>Description</entry>
<entry>Cardinality</entry>
<entry>Default value</entry>
</row>
</thead>
<tbody>
<row>
<entry>definition</entry>
<entry>The flow definition to be executed.</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>listeners</entry>
<entry>The set of observers observing the lifecycle of this flow execution.</entry>
<entry>
<emphasis>0..*</emphasis>
</entry>
<entry>Empty</entry>
</row>
<row>
<entry>attributes</entry>
<entry>Global system attributes that can be used to affect flow execution behavior</entry>
<entry>
<emphasis>0..*</emphasis>
</entry>
<entry>Empty</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The configurable constructs related to flow execution are shown graphically below:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecution-classdiagram.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecution-classdiagram.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Flow execution</para>
</caption>
</mediaobject>
</sect2>
<sect2 id="execution-impl-creation">
<title>Flow execution impl creation</title>
<programlisting>
FlowExecutionFactory factory = new FlowExecutionImplFactory();
factory.setExecutionListeners(...);
factory.setExecutionAttributes(...);
FlowExecution execution = factory.createFlowExecution(definition);
</programlisting>
</sect2>
</sect1>
<sect1 id="execution-context">
<title>Flow execution context</title>
<para>
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.
</para>
<para>
The contextual properties associated with a flow execution are summarized below:
</para>
<table>
<title>Flow Execution Context properties</title>
<tgroup cols="4">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Property name</entry>
<entry>Description</entry>
<entry>Cardinality</entry>
<entry>Default value</entry>
</row>
</thead>
<tbody>
<row>
<entry>active</entry>
<entry>
A flag indicating if the flow execution is active.
An inactive flow execution has either ended or has never been started.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>definition</entry>
<entry>
The definition of the flow execution. The flow definition serves as
the blueprint for the program. <emphasis>It may be helpful to think of a flow
definition as like a <literal>Class</literal> and a
flow execution as like an instance of that <literal>Class</literal></emphasis>.
This method may always be safely called.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>activeSession</entry>
<entry>
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.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>conversationScope</entry>
<entry>
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 <emphasis>shared</emphasis> by all flow sessions.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
As a flow execution is manipulated by clients its contextual state changes. Consider how
contextual state is effected when the following events occur:
</para>
<table>
<title>An ordered set of events and their effects on flow execution context</title>
<tgroup cols="3">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<thead>
<row>
<entry>Flow Execution Event</entry>
<entry>Active?</entry>
<entry>Value of the <literal>activeSession</literal> property</entry>
</row>
</thead>
<tbody>
<row>
<entry>created</entry>
<entry>false</entry>
<entry>Throws an IllegalStateException</entry>
</row>
<row>
<entry>started</entry>
<entry>true</entry>
<entry>
A <literal>FlowSession</literal> whose <literal>definition</literal>
is the top-level flow definition and whose <literal>state</literal> is the definition's start state.
</entry>
</row>
<row>
<entry>state entered</entry>
<entry>true</entry>
<entry>
A <literal>FlowSession</literal> whose <literal>definition</literal>
is the top-level flow definition and whose <literal>state</literal> is the newly entered state.
</entry>
</row>
<row>
<entry>subflow spawned</entry>
<entry>true</entry>
<entry>
A <literal>FlowSession</literal> whose <literal>definition</literal>
is the subflow definition and whose <literal>state</literal> is the subflow's start state.
</entry>
</row>
<row>
<entry>subflow ended</entry>
<entry>true</entry>
<entry>
A <literal>FlowSession</literal> whose <literal>definition</literal> is back to the
top-level flow definition and whose <literal>state</literal> is the resuming state.
</entry>
</row>
<row>
<entry>ended</entry>
<entry>false</entry>
<entry>Throws an IllegalStateException</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
As you can see, the <literal>activeSession</literal> 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 <emphasis>root session</emphasis>.
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.
</para>
<para>
The contextual properties associated with a <literal>FlowSession</literal> are summarized below:
</para>
<table>
<title>Flow Session properties</title>
<tgroup cols="4">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Property name</entry>
<entry>Description</entry>
<entry>Cardinality</entry>
<entry>Default value</entry>
</row>
</thead>
<tbody>
<row>
<entry>definition</entry>
<entry>
The definition of the flow the session is an instance of.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>state</entry>
<entry>
The current state of the session.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>status</entry>
<entry>
A status indicator describing what the session is currently doing.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>scope</entry>
<entry>
A data map that forms the basis for <emphasis>flow scope</emphasis>.
Arbitrary attributes placed in this map will be retained for the scope
of the flow session. This map is <emphasis>local</emphasis> to the session.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>flashMap</entry>
<entry>
A data map that forms the basis for <emphasis>flash scope</emphasis>.
Attributes placed in this map will be retained until the next
external user event is signaled in the session.
</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
The following graphic illustrates an example flow execution context and flow
session stack:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecution-sessionstack.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecution-sessionstack.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Flow execution context</para>
</caption>
</mediaobject>
<para>
In this illustration, a flow execution has been created for the <literal>Book Flight</literal> flow.
The execution is currently active and the <literal>activeSession</literal> indicates it
is in the <literal>Display Seating Chart</literal> state of the <literal>Assign Seats</literal> flow,
which was spawned as a subflow from the <literal>Enter Seat Assignments</literal> state.
</para>
<note>
<para>
Note how the active session status is <literal>paused</literal>, 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.
</para>
</note>
</sect1>
<sect1 id="execution-scopes">
<title>Flow execution scopes</title>
<para>
As alluded to, a flow execution manages several containers called <emphasis>scopes</emphasis>,
which allow arbitrary attributes to be stored for a period of time. There are four scope
types, each with different storage management semantics:
</para>
<table>
<title>Flow execution scope types</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<thead>
<row>
<entry>Scope type name</entry>
<entry>Management Semantics</entry>
</row>
</thead>
<tbody>
<row>
<entry>request</entry>
<entry>
Eligible for garbage collection when a single call into the flow execution completes.
</entry>
</row>
<row>
<entry>flash</entry>
<entry>
Cleared when the next user event is signaled into the flow session; eligible for garbage collection when the flow session ends.
</entry>
</row>
<row>
<entry>flow</entry>
<entry>
Eligible for garbage collection when the flow session ends.
</entry>
</row>
<row>
<entry>conversation</entry>
<entry>
Eligible for garbage collection when the root session of the governing flow execution (logical conversation) ends.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="execution-testing">
<title>Flow execution testing</title>
<para>
Spring Web Flow provides support within the <literal>org.springframework.webflow.test</literal>
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 <literal>new</literal> operator.
</para>
<para>
The general strategy for testing flows follows:
</para>
<para>
<orderedlist>
<listitem>
<para>
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
<literal>MockRequestContext</literal>.
</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
</orderedlist>
</para>
<note>
<para>
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.
</para>
</note>
<sect2 id="execution-testing-example">
<title>Flow execution test example</title>
<para>
To help illustrate testing a flow execution, first consider the following flow definition
to search a phonebook for contacts:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flow-search.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flow-search.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Phonebook Search Flow - State Diagram</para>
</caption>
</mediaobject>
<para>
The corresponding XML-based flow definition implementation:
</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;start-state idref="enterCriteria"/&gt;
&lt;view-state id="enterCriteria" view="searchCriteria"&gt;
&lt;render-actions&gt;
&lt;action bean="formAction" method="setupForm"/&gt;
&lt;/render-actions&gt;
&lt;transition on="search" to="displayResults"&gt;
&lt;action bean="formAction" method="bindAndValidate"/&gt;
&lt;/transition&gt;
&lt;/view-state&gt;
&lt;view-state id="displayResults" view="searchResults"&gt;
&lt;render-actions&gt;
&lt;bean-action bean="phonebook" method="search"&gt;
&lt;method-arguments&gt;
&lt;argument expression="flowScope.searchCriteria"/&gt;
&lt;/method-arguments&gt;
&lt;method-result name="results"/&gt;
&lt;/bean-action&gt;
&lt;/render-actions&gt;
&lt;transition on="newSearch" to="enterCriteria"/&gt;
&lt;transition on="select" to="browseDetails"/&gt;
&lt;/view-state&gt;
&lt;subflow-state id="browseDetails" flow="detail-flow"&gt;
&lt;attribute-mapper&gt;
&lt;input-mapper&gt;
&lt;mapping source="requestParameters.id" target="id" from="string" to="long"/&gt;
&lt;/input-mapper&gt;
&lt;/attribute-mapper&gt;
&lt;transition on="finish" to="displayResults"/&gt;
&lt;/subflow-state&gt;
&lt;/flow>
</programlisting>
<para>
Above you see a flow with three (3) states that execute these behaviors, respectively:
</para>
<para>
<orderedlist>
<listitem>
<para>
The first state <literal>enterCriteria</literal> displays a search criteria form so the user can enter who
he or she wishes to search for.
</para>
</listitem>
<listitem>
<para>
On form submit and successful data binding and validation, the search is executed.
After search execution a results view is displayed.
</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
</orderedlist>
</para>
<para>
From this behavior narrative the following assertable test scenarios can be extracted:
</para>
<orderedlist>
<listitem>
<para>
That when a flow execution starts, it enters the <literal>enterCriteria</literal> state and
makes a <literal>searchCriteria</literal> view selection containing a <emphasis>form object</emphasis>
to be used as the basis for form field population.
</para>
</listitem>
<listitem>
<para>
That on submit with valid input, the search is executed and a <literal>searchResults</literal> view selection is made.
</para>
</listitem>
<listitem>
<para>
That on submit with invalid input, the <literal>searchCriteria</literal> view is reselected.
</para>
</listitem>
<listitem>
<para>
That on newSearch, the <literal>searchCriteria</literal> view is selected.
</para>
</listitem>
<listitem>
<para>
That on select, the <literal>detail</literal> flow is spawned and passed the <literal>id</literal> of the selected result as expected.
</para>
</listitem>
</orderedlist>
<para>
To assist with writing these assertions, Spring Web Flow ships with JUnit-based flow execution
test support within the <literal>org.springframwork.webflow.test</literal> package.
These base test classes are indicated below:
</para>
<table>
<title>Flow execution test support hierarchy</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="3*" />
<colspec colname="c2" colwidth="4*" />
<thead>
<row>
<entry>Class name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>AbstractFlowExecutionTests</entry>
<entry>The most generic base class for flow execution tests.</entry>
</row>
<row>
<entry>AbstractExternalizedFlowExecutionTests</entry>
<entry>The base class for flow execution tests whose flow is defined within an externalized resource, such as a file.</entry>
</row>
<row>
<entry>AbstractXmlFlowExecutionTests</entry>
<entry>The base class for flow execution tests whose flow is defined within an externalized XML resource.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
</sect1>
</chapter>

View File

@@ -1,230 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="flow-executor">
<title>Flow executors</title>
<sect1 id="executor-intro">
<title>Introduction</title>
<para>
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.
</para>
<para>
In this chapter, you will learn how to execute flows within Spring MVC, Struts,
and Java Server Faces (JSF) based applications.
</para>
</sect1>
<sect1 id="executor">
<title>FlowExecutor</title>
<para>
<literal>org.springframework.webflow.executor.FlowExecutor</literal> 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.
</para>
<para>
The <literal>FlowExecutor</literal> interface is shown below:
</para>
<programlisting>
public interface FlowExecutor {
public void executeFlowRequest(ExternalContext context);
}
</programlisting>
<para>
Execution typically consists of either:
<orderedlist>
<listitem>
<para>
Launching (start) a new execution of a flow definition.
</para>
</listitem>
<listitem>
<para>
Resuming a paused flow execution by signaling an event against its current state.
</para>
</listitem>
</orderedlist>
</para>
<para>
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.
</para>
<para>
<literal>ExternalContext</literal> 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.
</para>
<sect2 id="flowexecutor-impl">
<title>FlowExecutorImpl</title>
<para>
The default executor implementation is <literal>org.springframework.webflow.executor.FlowExecutorImpl</literal>.
It allows for configuration of a <literal>FlowDefinitionLocator</literal> responsible for loading the flow definitions to execute, as well as
the <literal>FlowExecutionRepository</literal> strategy responsible for persisting flow executions that remain
active beyond a single request into the server.
</para>
<para>
The configurable <literal>FlowExecutorImpl</literal> properties are shown below:
</para>
<table>
<title>FlowExecutorImpl properties</title>
<tgroup cols="3">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c3" colwidth="2*" />
<thead>
<row>
<entry>Property name</entry>
<entry>Description</entry>
<entry>Cardinality</entry>
</row>
</thead>
<tbody>
<row>
<entry>definitionLocator</entry>
<entry>The service for loading flow definitions to be executed, typically a <literal>FlowDefinitionRegistry</literal></entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>executionFactory</entry>
<entry>The factory for creating new flow executions.</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
<row>
<entry>executionRepository</entry>
<entry>The repository for saving and loading persistent (paused) flow executions</entry>
<entry>
<emphasis>1</emphasis>
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="executor-simple">
<title>A typical flow executor configuration with Spring 2.0</title>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;!-- Launches new flow executions and resumes existing executions. --&gt;
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry"/>
&lt;!-- Creates the registry of flow definitions for this application --&gt;
&lt;web:flow-registry id="flowRegistry"&gt;
&lt;web:flow-location path="/WEB-INF/flows/**/*-flow.xml"/&gt;
&lt;/web:flow-registry&gt;
&lt;/beans&gt;
</programlisting>
<para>
This instructs Spring to create a flow executor that can execute all XML-based flow definitions
contained within the <literal>/WEB-INF/flows</literal> directory. The default flow execution
repository, <literal>continuation</literal>, is used.
</para>
</sect2>
<sect2 id="executor-custom-repo">
<title>A flow executor using a simple execution repository</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="simple"/&gt;
</programlisting>
<para>
This executor is configured with a simple repository that manages
execution state in the user session.
</para>
</sect2>
<sect2 id="executor-custom-repo2">
<title>A flow executor using a client-side continuation-based execution repository</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="client"/&gt;
</programlisting>
<para>
This executor is configured with a continuation-based repository that serializes
continuation state to the client using no server-side state.
</para>
</sect2>
<sect2 id="executor-custom-repo3">
<title>A flow executor using a single key execution repository</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="singleKey"/>&gt;
</programlisting>
<para>
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.
</para>
</sect2>
<sect2 id="executor-custom-repo4">
<title>A flow executor setting custom conversation management attributes</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry">
&lt;web:flow-repository type="continuation" max-conversations="5" max-continuations="30" conversation-manager-ref="conversationManager"/&gt;
&lt;/web:flow-executor&gt;
&lt;bean id="conversationManager" class="example.MyCustomConversationalStateManager"/&gt;
</programlisting>
<para>
This executor is configured with a continuation repository configured with custom settings for:
<orderedlist>
<listitem><para>The maximum number of active conversations per user session (5)</para></listitem>
<listitem><para>The maximum number of restorable flow execution snapshots (continuations) per conversation (30)</para></listitem>
<listitem><para>Where conversational state will be stored (via a custom conversationManager)</para></listitem>
</orderedlist>
The <literal>flow:repository</literal> child element is the more flexible form for configuring the flow execution repository.
Use it or the convenient <literal>repository-type</literal> attribute, not both.
</para>
</sect2>
<sect2 id="executor-excution-attributes">
<title>A flow executor setting system execution attributes</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"&gt;
&lt;web:flow-execution-attributes&gt;
&lt;web:alwaysRedirectOnPause value="false"/&gt;
&lt;web:attribute name="foo" value="bar"/&gt;
&lt;/flow:execution-attributes&gt;
&lt;/web:flow-executor&gt;
</programlisting>
<para>
This executor is configured to set two flow execution system attributes
<literal>alwaysRedirectOnPause=false</literal> and <literal>foo=bar</literal>.
</para>
<para>
<note>
<para>
The <literal>alwaysRedirectOnPause</literal> attribute determines if
a flow execution redirect occurs automatically each time an execution pauses
(automated <literal>POST+REDIRECT+GET</literal> behavior).
Setting this attribute to false will disable the <emphasis>default 'true' behavior</emphasis>.
</para>
</note>
</para>
</sect2>
<sect2 id="executor-excution-listeners">
<title>A flow executor setting custom execution listeners</title>
<programlisting>
&lt;web:flow-executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"&gt;
&lt;web:flow-execution-listeners&gt;
&lt;web:flow-listener ref="listener" criteria="order-flow"/&gt;
&lt;/web:flow-execution-listeners&gt;
&lt;/web:flow-executor&gt;
&lt;!-- A FlowExecutionListener to observe the lifecycle of order-flow executions --&gt;
&lt;bean id="listener" class="example.OrderFlowExecutionListener"/&gt;
</programlisting>
<para>
This executor is configured to apply the execution listener to the "order-flow".
</para>
</sect2>
</sect1>
</chapter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -3,20 +3,14 @@
"../lib/docbook-dtd/docbookx.dtd"
[
<!ENTITY overview SYSTEM "overview.xml">
<!ENTITY flow-definition SYSTEM "flow-definition.xml">
<!ENTITY flow-execution SYSTEM "flow-execution.xml">
<!ENTITY flow-execution-repository SYSTEM "flow-execution-repository.xml">
<!ENTITY flow-executor SYSTEM "flow-executor.xml">
<!ENTITY spring-faces SYSTEM "spring-faces.xml">
<!ENTITY practical SYSTEM "practical.xml">
<!ENTITY defining-flows SYSTEM "defining-flows.xml">
]>
<book>
<bookinfo>
<title>Spring Web Flow</title>
<subtitle>Reference Documentation</subtitle>
<releaseinfo>Version 2.0-m4</releaseinfo>
<releaseinfo>Version 2.0 M4</releaseinfo>
<pubdate>March 2008</pubdate>
<authorgroup>
<author>
@@ -54,11 +48,6 @@
<toc />
&overview;
&flow-definition;
&flow-execution;
&flow-execution-repository;
&flow-executor;
&spring-faces;
&practical;
&defining-flows;
</book>

View File

@@ -2,630 +2,50 @@
<preface id="preface">
<title>Preface</title>
<para>
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.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
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.
</para>
</preface>
<chapter id="introduction">
<title>Introduction</title>
<sect1 id="introduction-overview">
<title>Overview</title>
<sect1 id="manual-overview">
<title>What this guide covers</title>
<para>
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.
</para>
<para>
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
<emphasis>conversation</emphasis>.
Flows often execute across HTTP requests,
have state, exhibit transactional characteristics,
and may be dynamic and/or long-running in nature.
</para>
<para>
Spring Web Flow exists at a higher level of abstraction, integrating
as a self-contained <emphasis>flow engine</emphasis> 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.
</para>
</sect1>
<sect1 id="introduction-architecture-overview">
<title>Architecture overview</title>
<sect1 id="system-requirements">
<title>What Web Flow requires to run</title>
<para>
Spring Web Flow has been architected as a self-contained <emphasis>flow engine</emphasis>
with few required dependencies on third-party APIs. All dependencies are
carefully managed.
Java 1.4 or higher
</para>
<para>
At a minimum, to use Spring Web Flow you need:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>spring-webflow (the framework)</para>
</listitem>
<listitem>
<para>spring-core (miscellaneous utility classes used internally by the framework)</para>
</listitem>
<listitem>
<para>spring-binding (the Spring data binding framework, used internally)</para>
</listitem>
<listitem>
<para>commons-logging (a simple logging facade, used internally)</para>
</listitem>
<listitem>
<para>OGNL (the default expression language)</para>
</listitem>
</itemizedlist>
<para>
Most users will embed SWF as a component within a larger web application development
framework, as SWF is a focused <emphasis>controller technology</emphasis> 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.
</para>
<para>
<note>
<para>
Spring Web Flow, like Spring, is a <emphasis>layered</emphasis> 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 <emphasis>any</emphasis> environment.
</para>
</note>
Spring 2.5.2 or higher
</para>
</sect1>
<sect1 id="introduction-structure-layer-diagram">
<title>Architectural layers</title>
<sect1 id="support">
<title>Where to get additional support</title>
<para>
Spring Web Flow is a layered framework. A diagram of Spring Web Flow's layered architecture is
shown below:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/architecture-layer-diagram.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/architecture-layer-diagram.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Spring Web Flow layer diagram</para>
</caption>
</mediaobject>
</sect1>
<sect1 id="introduction-structure-layer-description">
<title>Layer descriptions</title>
<para>
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:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<emphasis>Subsystem name</emphasis> - The name of a layer subsystem.
</para>
</listitem>
<listitem>
<para>
<emphasis>Description</emphasis> - The purpose of the subsystem.
</para>
</listitem>
<listitem>
<para>
<emphasis>Packages</emphasis> - The Java packages that contain the source code for
the subsystem. The packages are rooted at the <literal>org.springframework.webflow</literal>
root package in the package hierarchy.
</para>
</listitem>
<listitem>
<para>
<emphasis>Subsystem interfaces</emphasis> - Central API elements exposed by the subsystem,
typically through Java interfaces.
</para>
</listitem>
<listitem>
<para>
<emphasis>Internal dependencies</emphasis> - Dependencies of the subsystem. These could be
other subsystems of the layer or external libraries.
</para>
</listitem>
</itemizedlist>
<sect2 id="layer-execution-core">
<title>The Execution Core Layer (Bottom Layer)</title>
<para>
Defines core flow definition and execution public APIs. As the "bottom layer", this
layer is highly stable with no dependencies on any other layer.
</para>
<table>
<title>Execution Core Subsystems</title>
<tgroup cols="5">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c3" colwidth="2*" />
<colspec colname="c4" colwidth="2*" />
<colspec colname="c5" colwidth="2*" />
<thead>
<row>
<entry>Subsystem name</entry>
<entry>Description</entry>
<entry>Packages</entry>
<entry>Subsystem interfaces</entry>
<entry>Internal dependencies</entry>
</row>
</thead>
<tbody>
<row>
<entry>Core</entry>
<entry>
Foundational, generic types usable by all other subsystems.
Contains the default expression parser (OGNL-based) and
core collection types (AttributeMap and company).
</entry>
<entry>
core,
core.collection
</entry>
<entry>None</entry>
<entry>None</entry>
</row>
<row>
<entry>Util</entry>
<entry>
Low level utilities used by all other parts of the system.
</entry>
<entry>
util
</entry>
<entry>None</entry>
<entry>None</entry>
</row>
<row>
<entry>Flow Definition</entry>
<entry>
Central abstractions for modeling flow definitions.
These abstractions include <literal>FlowDefinition</literal>,
<literal>StateDefinition</literal>, and <literal>TransitionDefinition</literal>
that form the domain language for describing flows.
</entry>
<entry>
definition
</entry>
<entry>
FlowDefinition
</entry>
<entry>Core</entry>
</row>
<row>
<entry>Flow Definition Registry</entry>
<entry>
Support for working with registries of flow definitions. Flow
definitions eligible for execution are typically stored in
a registry that provides lookup services.
</entry>
<entry>
definition.registry
</entry>
<entry>
FlowDefinitionRegistry,
FlowDefinitionLocator
</entry>
<entry>
Core,
Flow Definition
</entry>
</row>
<row>
<entry>External Context</entry>
<entry>
Provides normalized access to a client environment that has called into Spring Web Flow.
</entry>
<entry>
context,
context.servlet,
context.portlet
</entry>
<entry>
ExternalContext
</entry>
<entry>
Core,
context.servlet requires Servlet API 2.4,
context.portlet requires Portlet API 1.0 in addition to Servlet API 2.4
</entry>
</row>
<row>
<entry>Conversation</entry>
<entry>
Manages the creation and cleanup of conversational state. Used by
the execution repository system to begin new user conversations and
track execution state.
</entry>
<entry>
conversation,
conversation.impl
</entry>
<entry>
ConversationManager
</entry>
<entry>
Core,
Util,
External Context
</entry>
</row>
<row>
<entry>Flow Execution</entry>
<entry>
Stable runtime abstractions that define the flow definition
execution model. For executing flow definitions
and representing execution state.
</entry>
<entry>
execution,
execution.support,
execution.factory
</entry>
<entry>
FlowExecution
</entry>
<entry>
Core,
External Context,
Flow Definition
</entry>
</row>
<row>
<entry>Flow Execution Repository</entry>
<entry>
For persisting paused flow executions beyond a single request
into the server.
</entry>
<entry>
execution.repository,
execution.repository.support,
execution.repository.continuation
</entry>
<entry>
FlowExecutionRepository
</entry>
<entry>
Core,
Util,
Flow Definition,
Conversation,
Flow Execution
</entry>
</row>
<row>
<entry>Action</entry>
<entry>
Reusable action implementations.
</entry>
<entry>
action,
action.portlet
</entry>
<entry>
None
</entry>
<entry>
Core,
Util,
Flow Definition,
External Context,
Flow Execution
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="layer-execution-engine">
<title>The Execution Engine Layer</title>
<para>
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.
</para>
<para>
Depends On: Execution Core
</para>
<table>
<title>Execution Engine Subsystems</title>
<tgroup cols="5">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Subsystem name</entry>
<entry>Description</entry>
<entry>Packages</entry>
<entry>Subsystem interfaces</entry>
<entry>Internal dependencies</entry>
</row>
</thead>
<tbody>
<row>
<entry>Engine Implementation</entry>
<entry>
The implementation of the flow execution engine based on a finite state machine.
</entry>
<entry>
engine,
engine.support,
engine.impl
</entry>
<entry>None</entry>
<entry>None</entry>
</row>
<row>
<entry>Flow Definition Builder</entry>
<entry>
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.
</entry>
<entry>
engine.builder,
engine.builder.xml
</entry>
<entry>
<literal>FlowBuilder</literal>
</entry>
<entry>
Engine Implementation,
Spring Beans 2.0,
Spring Context 2.0,
<literal>builder.xml</literal> requires JDK 1.5 or Xerces for XSD support
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="layer-execution-test">
<title>The Test Layer</title>
<para>
Support for unit testing flow artifacts and system testing flow executions.
</para>
<para>
Depends On: Execution Engine, Execution Core
</para>
<table>
<title>Test Subsystems</title>
<tgroup cols="5">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Subsystem name</entry>
<entry>Description</entry>
<entry>Packages</entry>
<entry>Subsystem interfaces</entry>
<entry>Internal dependencies</entry>
</row>
</thead>
<tbody>
<row>
<entry>Engine Artifact Unit Test Support</entry>
<entry>
Support for unit testing implementations such as Actions in isolation.
</entry>
<entry>
test
</entry>
<entry>None</entry>
<entry>JUnit 3.8.1</entry>
</row>
<row>
<entry>Flow Execution Test Support</entry>
<entry>
Support for testing Flow Executions out-of-container.
</entry>
<entry>
test.execution
</entry>
<entry>None</entry>
<entry>
Spring Beans 2.0,
JUnit 3.8.1
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="layer-executor">
<title>The Executor Layer</title>
<para>
Stable higher-level layer for driving and coordinating the execution of flow definitions.
This layer is decoupled from the more-volatile engine implementation.
</para>
<para>
Depends On: Execution Core
</para>
<table>
<title>Executor Subsystems</title>
<tgroup cols="5">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Subsystem name</entry>
<entry>Description</entry>
<entry>Packages</entry>
<entry>Subsystem interfaces</entry>
<entry>Internal dependencies</entry>
</row>
</thead>
<tbody>
<row>
<entry>Core</entry>
<entry>
Generic flow executor abstractions and support.
</entry>
<entry>
executor,
executor.support
</entry>
<entry>
<literal>FlowExecutor</literal>
</entry>
<entry>None</entry>
</row>
<row>
<entry>Spring MVC</entry>
<entry>
The integration between Spring Web Flow and the Spring MVC framework.
</entry>
<entry>executor.mvc</entry>
<entry>None</entry>
<entry>
Core,
Spring Web MVC 2.0
</entry>
</row>
<row>
<entry>Struts</entry>
<entry>
The integration between Spring Web Flow and the Struts Classic framework.
</entry>
<entry>
executor.struts
</entry>
<entry>None</entry>
<entry>
Core,
Struts 1.1
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="layer-config">
<title>The System Configuration Layer (Top Layer)</title>
<para>
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.
</para>
<para>
Depends On: Executor, Execution Engine, Execution Core
</para>
<table>
<title>System Configuration Subsystems</title>
<tgroup cols="5">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<colspec colname="c2" colwidth="2*" />
<thead>
<row>
<entry>Subsystem name</entry>
<entry>Description</entry>
<entry>Packages</entry>
<entry>Subsystem interfaces</entry>
<entry>Internal dependencies</entry>
</row>
</thead>
<tbody>
<row>
<entry>Spring Configuration Support</entry>
<entry>
For configuring Spring Web Flow using Spring 1.x and 2.x.
</entry>
<entry>
config
</entry>
<entry>None</entry>
<entry>
Spring Beans 1.2.7,
<literal>spring-webflow-config-1.0</literal> XSD support requires Spring 2.0
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
<note>
<para>
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 <literal>ExternalContext</literal> 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.
</para>
</note>
</para>
<para>
For the exact list of dependencies, as well as supported product usage configurations,
see the Ivy dependency manager descriptor located within the SWF distribution.
</para>
</sect2>
</sect1>
<sect1 id="introduction-support">
<title>Support</title>
<para>
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
</para>
<para>
XML-based flow building requires Xerces 2 or JDK 5.0 (for XSD support).
</para>
<para>
Our active community support forum is located at http://forum.springframework.org.
Spring Community support is available at www.springframework.org
</para>
</sect1>
</chapter>

File diff suppressed because it is too large Load Diff

View File

@@ -1,382 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="spring-faces">
<title>Spring Faces</title>
<sect1 id="spring-faces-intro">
<title>Introduction</title>
<para>
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:
</para>
<para>
Unified EL Integration - A separate implementation of the <classname>ExpressionParser</classname> 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.
</para>
<para>
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.
</para>
</sect1>
<sect1 id="jsf-webflow">
<title>Web Flow Java Server Faces (JSF) integration</title>
<para>
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.
</para>
<para>
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.
</para>
<sect2 id="executor-jsf-simple">
<title>Adding Spring Web Flow extensions to a JSF application.</title>
<para>
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.
</para>
</sect2>
<sect2 id="executor-jsf-simple-webflow-setup">
<title>Configuring the Web Flow system</title>
<para>
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:
</para>
<programlisting>
&lt;!-- The front controller of the Spring Web application, responsible for handling all application requests --&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;Spring Web Servlet&lt;/servlet-name&gt;
&lt;servlet-class&gt;org.springframework.webflow.servlet.SpringWebServlet&lt;/servlet-class&gt;
&lt;init-param&gt;
&lt;param-name&gt;configLocations&lt;/param-name&gt;
&lt;param-value&gt;/WEB-INF/config/web-application-config.xml&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;!-- Map all /spring/* requests to the Spring Web Servlet for handling --&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;Spring Web Servlet&lt;/servlet-name&gt;
&lt;url-pattern&gt;/spring/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</programlisting>
<para>
The application context bootstrapped by the Spring Web Servlet should contain the Web Flow system configuration.
The example <literal>webflow-config.xml</literal> below shows a typical Web Flow configuration for a JSF environment:
</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;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"&gt;
&lt;!-- Imports the "application-layer" definining business logic and data access services --&gt;
&lt;import resource="application-layer-config.xml"/&gt;
&lt;web:flow-executor id="flowExecutor" flow-registry="flowRegistry"&gt;
&lt;web:flow-execution-listeners&gt;
&lt;web:listener ref="jpaFlowExecutionListener" criteria="*"/&gt;
&lt;/web:flow-execution-listeners&gt;
&lt;/web:flow-executor&gt;
&lt;web:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"&gt;
&lt;web:flow-location path="flow/main/main.xml" /&gt;
&lt;web:flow-location path="flow/booking/booking.xml" /&gt;
&lt;web:flow-builder class="org.springframework.faces.ui.resource.ResourcesFlowBuilder" /&gt;
&lt;/web:flow-registry&gt;
&lt;bean id="flowBuilderServices" class="org.springframework.webflow.engine.builder.support.FlowBuilderServices"&gt;
&lt;property name="expressionParser"&gt;
&lt;bean class="org.springframework.webflow.core.expression.el.WebFlowELExpressionParser"&gt;
&lt;constructor-arg &gt;
&lt;bean class="org.jboss.el.ExpressionFactoryImpl"/&gt;
&lt;/constructor-arg&gt;
&lt;/bean&gt;
&lt;/property&gt;
&lt;property name="viewFactoryCreator"&gt;
&lt;bean class="org.springframework.faces.webflow.JsfViewFactoryCreator"/&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</programlisting>
<para>
A bean named <literal>flowExecutor</literal> must be configured and linked with a flow definition registry
that contains the flows eligible for execution. Note the <literal>flowExecutor</literal> bean name is significant,
as that is bean name the Web Flow JSF extensions will expect.
</para>
<para>
Any flow executor property such as the flow execution repository type is configurable here, consistent
with the other environments Spring Web Flow supports.
</para>
<para>
The <literal>flowRegistry</literal> 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.
</para>
<para>
The <literal>flowBuilderServices</literal> provides a number of JSF-specific services to the <literal>flowRegistry</literal>, including the
<literal>WebFlowELExpressionParser</literal> that allows Web Flow to use the Unified EL for parsing expressions in flow definitions.
</para>
</sect2>
<sect2>
<title>Configuring the FacesServlet</title>
<para>
Even in an ideal scenario where the <literal>SpringWebServlet</literal> is handling all incoming requests, the <literal>FacesServlet</literal>
must still be configured in web.xml in order for JSF to bootstrap properly:
</para>
<programlisting>
&lt;!-- Here so the JSF implementation can initialize, not used at runtime --&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;
&lt;servlet-class&gt;javax.faces.webapp.FacesServlet&lt;/servlet-class&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;!-- Mapping for faces initialization --&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;
&lt;url-pattern&gt;*.faces&lt;/url-pattern&gt;
&lt;/servlet-mapping>
</programlisting>
<para>
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.
</para>
</sect2>
<sect2 id="executor-jsf-launch-normal-anchor">
<title>Launching a flow execution - normal HTML anchor</title>
<para>
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:
</para>
<programlisting>
&lt;a href="/spring/main"&gt;Go&lt;/a&gt;
</programlisting>
<para>
This link would launch the "main" flow, assuming /spring/* has been mapped to the <literal>SpringWebServlet</literal> defined within web.xml.
</para>
</sect2>
<sect2 id="executor-jsf-launch-commandlink">
<title>Launching a flow execution - JSF command link component</title>
<para>
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 <literal>action</literal> 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.
</para>
<programlisting>
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();
}
</programlisting>
</sect2>
<sect2 id="executor-jsf-sampleflow">
<title>Flow definitions in a JSF environment</title>
<para>
Flow definitions in a JSF environment are just plain Spring Web Flow definitions:
</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;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">
&lt;var name="myBean" class="example.ManagedBeanImpl" scope="conversation" /&gt;
&lt;start-state idref="displayView" /&gt;
&lt;view-state id="displayView" view="myview.jsp"&gt;
&lt;transition on="submit" to="prepareNextView"/&gt;
&lt;/view-state>
&lt;action-state id="prepareNextView" &gt;
&lt;bean-action bean="myService" method="loadMyModel"&gt;
&lt;method-arguments&gt;
&lt;argument expression="#{myBean.foo}"/&gt;
&lt;/method-arguments&gt;
&lt;/bean-action&gt;
&lt;transition on="success" to="displayNextView"/&gt;
&lt;/action-state&gt;
&lt;view-state id="displayNextView" view="mynextview.jsp" /&gt;
&lt;/flow&gt;
</programlisting>
<para>
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.
</para>
<para>
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".
</para>
<para>
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.
</para>
</sect2>
<sect2 id="executor-jsf-resume-form">
<title>Resuming a flow execution - form bound to flow execution variables</title>
<para>
Views participating in flows are just plain JSF views. They may also incorporate other
JSF view technologies such as Facelets and Ajax4JSF.
</para>
<programlisting>
&lt;f:view&gt;
&lt;h:form id="form"&gt;
...
&lt;h:inputText id="propertyName" value="#{someBean.someProperty}"/&gt;
...
&lt;h:commandButton type="submit" value="Next" action="submit"/&gt;
&lt;/h:form&gt;
&lt;/f:view&gt;
</programlisting>
<para>
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.
</para>
</sect2>
<sect2 id="spring-faces-components">
<title>Spring Faces JSF Components</title>
<para>
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.
</para>
<sect3>
<title>Spring Faces Component Configuration</title>
<para>
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:
</para>
<programlisting>
xmlns:sf="http://www.springframework.org/tags/faces"
</programlisting>
</sect3>
<sect3>
<title>Spring Faces Resource Loading</title>
<para>
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:
<orderedlist>
<listitem>
1) Look for the resource in the web app root using the context-relative path "/dojo/dojo.js", and serve the resource if found.
</listitem>
<listitem>
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.
</listitem>
</orderedlist>
</para>
<para>
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.
</para>
</sect3>
<sect3>
<title>Using The Spring Faces Client Side Validation Components</title>
<para>
Spring Faces provides three different client-side validator components:
</para>
<para>
<orderedlist>
<listitem>
<para>
&lt;sf:clientTextValidator&gt; - Provides validation with customizable error messages for text fields.
</para>
</listitem>
<listitem>
<para>
&lt;sf:clientNumberValidator&gt; - Provides validation and input filtering with customizable error messages for numeric
fields.
</para>
</listitem>
<listitem>
<para>
&lt;sf:clientDateValidator&gt; - Provides validation and a rich popup date picker control with customizable error
messages for date fields.
</para>
</listitem>
<listitem>
<para>
&lt;sf:validateAllOnClick&gt; - When wrapped around a UICommand component such as &lt;h:commandButton&gt; or &lt;h:commandLink&gt;
fires all client-side validators when the UICommand component is clicked and prevents the form from being submitted if
any of the validations fail.
</para>
</listitem>
</orderedlist>
</para>
<para>
The validator components must be wrapped around an &lt;h:inputText&gt; component (or any other component that renders an HTML text input).
For example, see the following snippet from the Booking sample application:
</para>
<para>
<programlisting>
&lt;sf:clientDateValidator required="true"&gt;
&lt;h:inputText id="checkinDate" value="#{booking.checkinDate}" required="true"&gt;
&lt;f:convertDateTime pattern="yyyy-MM-dd" timeZone="EST"/&gt;
&lt;/h:inputText&gt;
&lt;/sf:clientDateValidator&gt;
</programlisting>
</para>
<para>
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.
</para>
<para>
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.
</para>
</sect3>
<sect3>
<title>Using Ext Version of The Spring Faces Client Side Validation Components</title>
<para>
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:
</para>
<programlisting>
xmlns:sfe="http://www.springframework.org/tags/faces-ext"
</programlisting>
<para>
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.
</para>
</sect3>
</sect2>
<sect2 id="executor-jsf-sample">
<title>Spring Web Flow JSF Integration Samples</title>
<para>
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.
</para>
</sect2>
</sect1>
</chapter>