Moved Spring Web Flow to a top level project

This commit is contained in:
Ben Hale
2006-12-21 16:02:27 +00:00
commit e7ecbbc7e5
1083 changed files with 80775 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
lib
target

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 968 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

View File

@@ -0,0 +1,20 @@
This project uses the 'DocBook XSL distribution' for HTML and PDF
generation of project reference documentation.
This project's build.xml file contains targets to generate the
project reference documentation.
To generate project documentation, execute one of the following
build targets:
* doc-all - generate documentation in all formats
* doc-pdf - generate the PDF documentation
* doc-html - generate the HTML documentation
* doc-htmlsingle - generate single page HTML documentation
* doc-clean - clean any output directories for docs
For generation to complete successfully, you must have first extracted
the .jar libraries contained in this archive:
- http://static.springframework.org/spring/files/docbook-reference-libs.zip
... to ${basedir}/docs/reference. If you have not yet done so, download this file
and unzip the contents of the archive into ${basedir}/docs/reference.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,247 @@
<?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 their use 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 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 flow execution is created it marks the start of a new conversation between a browser
and the server. As outlined, 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 been ended the conversation identifier is no longer valid
and cannot ever 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

@@ -0,0 +1,809 @@
<?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'll
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, typically 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>
MutableAttributeMap input = ...
ExternalContext context = ...
ViewSelection startingView = execution.start(input, 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 the input to be provided. After pausing the
<literal>ViewSelection</literal> returned is typically used to issue a response to the user
that provides a vehicle for collecting the required input.
</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 = ...
ViewSelection nextView = execution.signalEvent("submit", 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
<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-1.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>
<para>
The completed test for this example extending <literal>AbstractXmlFlowExecutionTests</literal> is shown below:
</para>
<programlisting>
public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests {
public void testStartFlow() {
ApplicationView view = applicationView(startFlow());
assertCurrentStateEquals("enterCriteria");
assertViewNameEquals("searchCriteria", view);
assertModelAttributeNotNull("searchCriteria", view);
}
public void testCriteriaSubmitSuccess() {
startFlow();
MockParameterMap parameters = new MockParameterMap();
parameters.put("firstName", "Keith");
parameters.put("lastName", "Donald");
ApplicationView view = applicationView(signalEvent("search", parameters));
assertCurrentStateEquals("displayResults");
assertViewNameEquals("searchResults", view);
assertModelAttributeCollectionSize(1, "results", view);
}
public void testCriteriaSubmitError() {
startFlow();
signalEvent("search");
assertCurrentStateEquals("enterCriteria");
}
public void testNewSearch() {
testCriteriaSubmitSuccess();
ApplicationView view = applicationView(signalEvent("newSearch"));
assertCurrentStateEquals("enterCriteria");
assertViewNameEquals("searchCriteria", view);
}
public void testSelectValidResult() {
testCriteriaSubmitSuccess();
MockParameterMap parameters = new MockParameterMap();
parameters.put("id", "1");
ApplicationView view = applicationView(signalEvent("select", parameters));
assertCurrentStateEquals("displayResults");
assertViewNameEquals("searchResults", view);
assertModelAttributeCollectionSize(1, "results", view);
}
@Override
protected FlowDefinitionResource getFlowDefinitionResource() {
return createFlowDefinitionResource("src/main/webapp/WEB-INF/flows/search-flow.xml");
}
@Override
protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
Flow mockDetailFlow = new Flow("detail-flow");
mockDetailFlow.setInputMapper(new AttributeMapper() {
public void map(Object source, Object target, Map context) {
assertEquals("id of value 1 not provided as input by calling search flow", new Long(1), ((AttributeMap)source).get("id"));
}
});
// test responding to finish result
new EndState(mockDetailFlow, "finish");
serviceRegistry.registerSubflow(mockDetailFlow);
serviceRegistry.registerBean("phonebook", new ArrayListPhoneBook());
}
}
</programlisting>
<para>
With a well-written flow execution test passing that covers the controller behavior scenarios
possible for your flow you have concrete evidence the flow will execute as expected when
deployed in a container.
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/junit-greenbar.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/junit-greenbar.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Go for Green</para>
</caption>
</mediaobject>
</sect2>
<sect2 id="execution-testing-system">
<title>Execution unit testing vs. full-blown system testing</title>
<para>
The previous example shows how to test a flow execution in relative isolation with a mock service
layer and mock subflows. Flow execution testing against a real service-layer
and real subflows is also supported.
</para>
<para>
The next example shows how the <literal>createFlowServiceLocator</literal> method can
be overridden to create the service-layer using a Spring application context:
</para>
<programlisting>
public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests {
...
@Override
protected FlowDefinitionResource getFlowDefinitionResource() {
return createFlowDefinitionResource("src/main/webapp/WEB-INF/flows/search-flow.xml");
}
@Override
protected FlowServiceLocator createFlowServiceLocator() {
// create a context to host our middle tier services
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {
"classpath:service-layer-config.xml",
"classpath:data-access-layer-config.xml"
});
// create a registry for our flow definitions being tested
FlowDefinitionRegistry registry = new FlowDefinitionRegistryImpl();
// initialize the service locator
DefaultFlowServiceLocator locator = new DefaultFlowServiceLocator(registry, context);
// perform subflow definition registration with the help of a registrar
XmlFlowRegistrar registrar = new XmlFlowRegistrar(locator);
registrar.addResource(createFlowDefinitionResource("/WEB-INF/flows/search-flow.xml"));
registrar.addResource(createFlowDefinitionResource("/WEB-INF/flows/detail-flow.xml"));
registrar.registerFlowDefinitions(registry);
return locator;
}
}
</programlisting>
</sect2>
</sect1>
</chapter>

View File

@@ -0,0 +1,555 @@
<?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'll 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 {
ResponseInstruction launch(String flowDefinitionId, ExternalContext context);
ResponseInstruction resume(String flowExecutionKey, String eventId, ExternalContext context);
ResponseInstruction refresh(String flowExecutionKey, ExternalContext context);
}
</programlisting>
<para>
As you can see there are three central use-cases fulfilled by this interface:
<orderedlist>
<listitem>
<para>
Launch (start) a new execution of a flow definition.
</para>
</listitem>
<listitem>
<para>
Resume a paused flow execution by signaling an event against its current state.
</para>
</listitem>
<listitem>
<para>
Request that the last response issued by a flow execution be re-issued.
Unlike start and signalEvent, the refresh operation is an idempotent operation
that does not affect the state of a flow execution.
</para>
</listitem>
</orderedlist>
</para>
<para>
Each operation accepts an <literal>ExternalContext</literal> that provides normalized
access to properties of an external system that has called into Spring Web Flow, allowing
access to environment-specific request parameters as well as request, session, and
application-level attributes.
</para>
<para>
Each operation returns a <literal>ResponseInstruction</literal> which the calling system is
expected to use to issue a suitable response.
</para>
<para>
These relationships are shown graphically below:
</para>
<mediaobject>
<imageobject role="fo">
<imagedata fileref="images/flowexecutorfacade-classdiagram.png" format="PNG" align="center"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/flowexecutorfacade-classdiagram.png" format="PNG" align="center"/>
</imageobject>
<caption>
<para>Flow executor</para>
</caption>
</mediaobject>
<para>
As you can see, an <literal>ExternalContext</literal> implementation exists 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 special 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:flow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-1.0.xsd"&gt;
&lt;!-- Launches new flow executions and resumes existing executions. --&gt;
&lt;flow:executor id="flowExecutor" registry-ref="flowRegistry"/>
&lt;!-- Creates the registry of flow definitions for this application --&gt;
&lt;flow:registry id="flowRegistry"&gt;
&lt;flow:location path="/WEB-INF/flows/**/*-flow.xml"/&gt;
&lt;/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;flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="simple"/>
</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;flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="client"/>
</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;flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="singleKey"/>
</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-excution-attributes">
<title>A flow executor setting system execution attributes</title>
<programlisting>
&lt;flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"&gt;
&lt;flow:execution-attributes&gt;
&lt;flow:alwaysRedirectOnPause value="false"/&gt;
&lt;flow:attribute name="foo" value="bar"/&gt;
&lt;/flow:execution-attributes&gt;
&lt;/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>
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>
where a flow execution redirect always occurs on pause.
</note>
</para>
</sect2>
<sect2 id="executor-excution-listeners">
<title>A flow executor setting custom execution listeners</title>
<programlisting>
&lt;flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation"&gt;
&lt;flow:execution-listeners&gt;
&lt;flow:listener ref="listener" criteria="order-flow"/&gt;
&lt;/flow:execution-listeners&gt;
&lt;/flow-executor&gt;
&lt;!-- A FlowExecutionListener to observe the lifecycle of order-flow executions --&gt;
&lt;bean id="listener" class="org.springframework.webflow.samples.sellitem.SellItemFlowExecutionListener"/&gt;
</programlisting>
<para>
This executor is configured to apply the execution listener to the "order-flow".
</para>
</sect2>
<sect2 id="executor-1.2-compatible">
<title>A Spring 1.2 compatible flow executor configuration</title>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"&gt;
&lt;beans&gt;
&lt;!-- Launches new flow executions and resumes existing executions: Spring 1.2 config version --&gt;
&lt;bean id="flowExecutor" class="org.springframework.webflow.config.FlowExecutorFactoryBean"&gt;
&lt;property name="definitionLocator" ref="flowRegistry"/&gt;
&lt;property name="executionAttributes"&gt;
&lt;map&gt;
&lt;entry key="alwaysRedirectOnPause"&gt;
&lt;value type="java.lang.Boolean"&gt;false&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;property name="repositoryType" value="CONTINUATION"/&gt;
&lt;/bean&gt;
&lt;!-- Creates the registry of flow definitions for this application: Spring 1.2 config version --&gt;
&lt;bean id="flowRegistry"
class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean"&gt;
&lt;property name="flowLocations"&gt;
&lt;list&gt;
&lt;value&gt;/WEB-INF/flows/**/*-flow.xml&lt;/value&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;/beans&gt;
</programlisting>
<para>
This achieves similar semantics as the Spring 2.0 version above.
The 2.0 version is more concise, provides stronger validation, and encapsulates
internal details such as FactoryBean class names. The 1.2 version is Spring 1.2 or >
compatible and digestable by Spring IDE 1.3.
</para>
</sect2>
</sect1>
<sect1 id="executor-mvc">
<title>Spring MVC integration</title>
<para>
Spring Web Flow integrates with both Servlet and Portlet MVC which ship with the
core Spring Framework. Use of Portlet MVC requires Spring 2.0.
</para>
<para>
For both Servlet and Portlet MVC a <literal>FlowController</literal> acts as an adapter
between Spring MVC and Spring Web Flow. As an adapter, this controller has knowledge
of both systems and delegates to a flow executor for driving the execution of flows.
One controller typically executes all flows of an application, relying on
parameterization to determine what flow to launch or what flow execution to resume.
</para>
<sect2 id="executor-servletmvc">
<title>A single flow controller executing all flows in a Servlet MVC environment</title>
<programlisting>
&lt;bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController"&gt;
&lt;property name="flowExecutor" ref="flowExecutor"/&gt;
&lt;/bean&gt;
</programlisting>
<para>
This controller, exported at the context-relative <literal>/flowController.htm</literal> URL,
delegates to the configured flow executor for driving flow executions in a Spring Servlet
MVC environment.
</para>
</sect2>
<sect2 id="executor-portletmvc">
<title>A single portlet flow controller executing a flow within a Portlet</title>
<programlisting>
&lt;bean id="portletModeControllerMapping"
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
&lt;property name="portletModeMap">
&lt;map&gt;
&lt;entry key="view" value-ref="flowController"/&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="flowController" class="org.springframework.webflow.executor.mvc.PortletFlowController"&gt;
&lt;property name="flowExecutor" ref="flowExecutor"/&gt;
&lt;property name="defaultFlowId" ref="search-flow"/&gt;
&lt;/bean&gt;
</programlisting>
<para>
This controller, exported for access with the configured portlet mode,
delegates to the configured flow executor for driving flow executions in a Spring Portlet
MVC environment (by default, an execution of the <literal>search-flow</literal>
will be launched).
</para>
</sect2>
</sect1>
<sect1 id="executor-parameterization">
<title>Flow executor parameterization</title>
<para>
Spring Web Flow allows for full control over how flow executor method arguments such as the
<literal>flowDefinitionId</literal>, <literal>flowExecutionKey</literal>, and <literal>eventId</literal>
are extracted from an incoming controller request with the
<literal>org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor</literal>
strategy.
<note>
The various flow controllers typically do not use this strategy directly but instead use a
convenient <literal>FlowExecutorArgumentHandler</literal> implementation that takes care
of argument extraction as well as exposing responsibilities (in callback URLs).
</note>
</para>
<para>
The next several examples illustrate strategies for parameterizing flow controllers
from the browser to launch and resume flow executions:
</para>
<sect2 id="executor-parmeterization-default">
<title>Request parameter-based flow executor argument extraction</title>
<para>
The default executor argument extractor strategy is request-parameter based.
The default request parameters are:
</para>
<table>
<title>Extractor request parameter names</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="2*" />
<colspec colname="c2" colwidth="4*" />
<thead>
<row>
<entry>Parameter name</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>_flowId</entry>
<entry>The flow definition id, needed to launch a new flow execution.</entry>
</row>
<row>
<entry>_flowExecutionKey</entry>
<entry>The flow execution key, needed to resume and refresh an existing flow execution.</entry>
</row>
<row>
<entry>_eventId</entry>
<entry>The id of an event that occured, needed to resume an existing flow execution.</entry>
</row>
</tbody>
</tgroup>
</table>
<sect3 id="executor-mvc-launch-get">
<title>Launching a flow execution - parameter-style anchor</title>
<programlisting>
&lt;a href="flowController.htm?_flowId=myflow"&gt;Launch My Flow&lt;/a&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-launch-post">
<title>Launching a flow execution - form</title>
<programlisting>
&lt;form action="flowController.htm" method="post"&gt;
&lt;input type="submit" value="Launch My Flow"/>
&lt;input type="hidden" name="_flowId" value="myflow"&gt;
&lt;/form&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-resume-anchor">
<title>Resuming a flow execution - anchor</title>
<programlisting>
&lt;a href="flowController.htm?_flowExecutionKey=${flowExecutionKey}&amp;_eventId=submit"&gt;
Submit
&lt;/a&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-resume-form">
<title>Resuming a flow execution - form</title>
<programlisting>
&lt;form action="flowController.htm" method="post"&gt;
...
&lt;input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"&gt;
&lt;input type="hidden" name="_eventId" value="submit"/>
&lt;input type="submit" class="button" value="Submit"&gt;
&lt;/form&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-resume-form-buttons">
<title>Resuming a flow execution - multiple form buttons</title>
<programlisting>
&lt;form action="flowController.htm" method="post"&gt;
...
&lt;input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"&gt;
&lt;input type="submit" class="button" name="_eventId_submit" value="Submit"&gt;
&lt;input type="submit" class="button" name="_eventId_cancel" value="Cancel"&gt;
&lt;/form&gt;
</programlisting>
<note>
<para>
In this case the <literal>eventId</literal> is determined by parsing the name of the
button that was pressed.
</para>
</note>
</sect3>
<sect3 id="executor-mvc-refresh">
<title>Refreshing a flow execution</title>
<programlisting>
&lt;a href="flowController.htm?_flowExecutionKey=${flowExecutionKey}"&gt;Refresh&lt;/a&gt;
</programlisting>
</sect3>
</sect2>
<sect2 id="executor-extraction-requestpath">
<title>Request path based flow executor argument extraction</title>
<para>
The request-path based argument extractor strategy relies on executor arguments
being path elements as much as possible. This results in friendlier REST-style URLs such
as <literal>http://host/app/myflow</literal> instead of
<literal>http://host/app?_flowId=myflow</literal>.
</para>
<sect3 id="executor-servletmvc-pathextractor">
<title>A flow controller with a request-path based argument extractor</title>
<programlisting>
&lt;bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController"&gt;
&lt;property name="flowExecutor" ref="flowExecutor"/&gt;
&lt;property name="argumentHandler"&gt;
&lt;bean class="org.springframework.webflow.executor.support.RequestPathFlowExecutorArgumentHandler"/&gt;
&lt;/property&gt;
&lt;/bean&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-launch-get-rest">
<title>Launching a flow execution - REST-style anchor</title>
<programlisting>
&lt;a href="flowController/myflow"/&gt;Launch My Flow&lt;/a&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-resume-form-buttons-requestpath">
<title>Resuming a flow execution - multiple form buttons</title>
<programlisting>
&lt;form action="${flowExecutionKey}" method="post"&gt;
...
&lt;input type="submit" class="button" name="_eventId_submit" value="Submit"&gt;
&lt;input type="submit" class="button" name="_eventId_cancel" value="Cancel"&gt;
&lt;/form&gt;
</programlisting>
</sect3>
<sect3 id="executor-mvc-refresh-requestpath">
<title>Refreshing a flow execution</title>
<programlisting>
&lt;a href="flowController/k/${flowExecutionKey}"&gt;Refresh&lt;/a&gt;
</programlisting>
</sect3>
</sect2>
</sect1>
<sect1 id="executor-struts">
<title>Struts integration</title>
<para>
Spring Web Flow integrates with Struts 1.x or >. The integration is very similiar to
Spring MVC where a single front controller (FlowAction) drives the execution of all flows
for the application by delegating to a configured flow executor.
</para>
<sect2 id="executor-struts-simple">
<title>A single flow action executing all flows</title>
<programlisting>
&lt;form-beans&gt;
&lt;form-bean name="actionForm" type="org.springframework.web.struts.SpringBindingActionForm"/&gt;
&lt;/form-beans&gt;
&lt;action-mappings&gt;
&lt;action path="/flowAction" name="actionForm" scope="request"
type="org.springframework.webflow.executor.struts.FlowAction"/&gt;
&lt;/action-mappings&gt;
</programlisting>
</sect2>
</sect1>
<sect1 id="executor-jsf">
<title>Java Server Faces (JSF) integration</title>
<para>
Spring Web Flow integrates with JSF. The JSF integration relies on custom implementations of
core JSF artifacts such as navigation handler and phase listener to drive the
execution of flows.
</para>
<sect2 id="executor-jsf-simple">
<title>A typical faces-config.xml file</title>
<programlisting>
&lt;faces-config&gt;
&lt;application&gt;
&lt;navigation-handler&gt;
org.springframework.webflow.executor.jsf.FlowNavigationHandler
&lt;/navigation-handler&gt;
&lt;property-resolver&gt;
org.springframework.webflow.executor.jsf.FlowPropertyResolver
&lt;/property-resolver&gt;
&lt;variable-resolver&gt;
org.springframework.webflow.executor.jsf.FlowVariableResolver
&lt;/variable-resolver&gt;
&lt;variable-resolver&gt;
org.springframework.web.jsf.DelegatingVariableResolver
&lt;/variable-resolver&gt;
&lt;variable-resolver>
org.springframework.web.jsf.WebApplicationContextVariableResolver
&lt;/variable-resolver&gt;
&lt;/application&gt;
&lt;lifecycle&gt;
&lt;phase-listener&gt;org.springframework.webflow.executor.jsf.FlowPhaseListener&lt;/phase-listener&gt;
&lt;/lifecycle&gt;
&lt;/faces-config&gt;
</programlisting>
</sect2>
<sect2 id="executor-jsf-launch-get">
<title>Launching a flow execution - command link</title>
<programlisting>
&lt;h:commandLink value="Go" action="flowId:myflow"/&gt;
</programlisting>
</sect2>
<sect2 id="executor-jsf-resume-form">
<title>Resuming a flow execution - form</title>
<programlisting>
&lt;h:form id="form"&gt;
...
&lt;h:inputText id="propertyName" value="#{flowScope.managedBeanName.propertyName}"/&gt;
...
&lt;input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"&gt;
&lt;h:commandButton type="submit" value="Next" action="submit"/&gt;
&lt;/h:form&gt;
</programlisting>
</sect2>
</sect1>
</chapter>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -0,0 +1,79 @@
<?xml version='1.0' encoding="iso-8859-1"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"../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 practical SYSTEM "practical.xml">
]>
<book>
<bookinfo>
<title>Spring Web Flow</title>
<subtitle>Reference Documentation</subtitle>
<releaseinfo>Version 1.0</releaseinfo>
<pubdate>October 2006</pubdate>
<authorgroup>
<author>
<firstname>Keith</firstname>
<surname>Donald</surname>
</author>
<author>
<firstname>Erwin</firstname>
<surname>Vervaet</surname>
</author>
</authorgroup>
<legalnotice>
<para>
Copies of this document may be made for your own use and for
distribution to others, provided that you do not charge any
fee for such copies and further provided that each copy
contains this Copyright Notice, whether distributed in print
or electronically.
</para>
</legalnotice>
</bookinfo>
<dedication>
<title>Sponsors</title>
<para>
<emphasis>
Spring Web Flow would not be possible without the investment of its sponsors:
<ulink url="http://www.interface21.com/">Interface21</ulink> and
<ulink url="http://www.ervacon.com">Ervacon</ulink>.
</emphasis>
</para>
<para>
<inlinemediaobject>
<imageobject role="fo">
<imagedata fileref="images/logo-interface21.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/logo-interface21.png" format="PNG"/>
</imageobject>
</inlinemediaobject>
<inlinemediaobject>
<imageobject role="fo">
<imagedata fileref="images/logo-ervacon.png" format="PNG"/>
</imageobject>
<imageobject role="html">
<imagedata fileref="images/logo-ervacon.png" format="PNG"/>
</imageobject>
</inlinemediaobject>
</para>
</dedication>
<toc />
&overview;
&flow-definition;
&flow-execution;
&flow-execution-repository;
&flow-executor;
&practical;
</book>

View File

@@ -0,0 +1,646 @@
<?xml version="1.0" encoding="UTF-8"?>
<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.
</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.
</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.
</para>
</preface>
<chapter id="introduction">
<title>Introduction</title>
<sect1 id="introduction-overview">
<title>Overview</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.
</para>
</sect1>
<sect1 id="introduction-architecture-overview">
<title>Architecture overview</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.
</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>
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.
</note>
</para>
</sect1>
<sect1 id="introduction-structure-layer-diagram">
<title>Architectural layers</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 providing 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.3,
context.portlet requires Portlet API 1.0 in addition to Servlet API 2.3
</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,
repository.continuation requires commons-codec 1.0 if using client continuations
</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 1.2.7,
Spring Context 1.2.7,
<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 1.2.7,
JUnit 3.8.1
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
<sect2 id="layer-executor">
<title>The Executor Layer</title>
<para>
Stable higher-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>
Stable, 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 1.2.7,
Portlet MVC requires Spring 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>
<row>
<entry>Java Server Faces (JSF)</entry>
<entry>
The integration between Spring Web Flow and the Java Server Faces framework.
</entry>
<entry>
executor.jsf
</entry>
<entry>None</entry>
<entry>
Core,
JSF 1.0
</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>
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.
</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.0 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.
</para>
<para>
XML-based flow building requires Xerces 2 or JDK 5.0 (for XSD support).
</para>
<para>
The Spring Web Flow Portlet integration requires Spring Portlet MVC 2.0.
</para>
<para>
Our active community support forum is located at http://forum.springframework.org.
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="practical">
<title>Practical Use of Spring Web Flow</title>
<sect1 id="samples">
<title>Sample applications</title>
<para>
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:
</para>
<para>
<orderedlist>
<listitem>
<para>Phonebook - the original sample demonstrating most features (including subflows).</para>
</listitem>
<listitem>
<para>Sellitem - demonstrates a wizard with conditional transitions, flow scope, flow execution redirects, and continuations.</para>
</listitem>
<listitem>
<para>Flowlauncher - demonstrates all the possible ways to launch and resume flows.</para>
</listitem>
<listitem>
<para>Itemlist - demonstrates REST-style URLs and inline flows.</para>
</listitem>
<listitem>
<para>Shippingrate - demonstrates Spring Web Flow together with Ajax technology.</para>
</listitem>
<listitem>
<para>NumberGuess - demonstrates use of stateful middle-tier components to carry out business logic.</para>
</listitem>
<listitem>
<para>Birthdate - demonstrates Struts integration and the MultiAction.</para>
</listitem>
<listitem>
<para>Fileupload - demonstrates multipart file upload.</para>
</listitem>
<listitem>
<para>Phonebook-Portlet - the phonebook sample in a Portlet environment (notice how the flow definitions do not change).</para>
</listitem>
<listitem>
<para>Sellitem-JSF - the sellitem sample in a JSF environment (notice how the flow definition is more concise because
JSF takes care of data binding and validation).</para>
</listitem>
</orderedlist>
</para>
</sect1>
</chapter>

View File

@@ -0,0 +1,475 @@
<?xml version="1.0"?>
<!--
This is the XSL FO (PDF) stylesheet for the Spring reference
documentation.
Thanks are due to Christian Bauer of the Hibernate project
team for writing the original stylesheet upon which this one
is based.
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY db_xsl_path "../lib/docbook-xsl/">
<!ENTITY admon_gfx_path "../images/admons/">
<!ENTITY copyright "&#xA9;">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns="http://www.w3.org/TR/xhtml1/transitional"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="#default">
<xsl:import href="&db_xsl_path;/fo/docbook.xsl"/>
<!--###################################################
Custom Title Page
################################################### -->
<xsl:template name="book.titlepage.recto">
<fo:block>
<fo:table table-layout="fixed" width="175mm">
<fo:table-column column-width="175mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block>
<fo:external-graphic src="file:images/logo.jpg"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="22pt" padding-before="10mm">
<xsl:value-of select="bookinfo/subtitle"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:value-of select="bookinfo/releaseinfo"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="14pt" padding="10mm">
<xsl:value-of select="bookinfo/pubdate"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:text>Copyright &copyright; 2004-2006 </xsl:text>
<xsl:for-each select="bookinfo/authorgroup/author">
<xsl:if test="position() > 1">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="surname"/>
</xsl:for-each>
</fo:block>
<fo:block font-family="Helvetica" font-size="10pt" padding="1mm">
<xsl:value-of select="bookinfo/legalnotice"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
<!-- Prevent blank pages in output -->
<xsl:template name="book.titlepage.before.verso">
</xsl:template>
<xsl:template name="book.titlepage.verso">
</xsl:template>
<xsl:template name="book.titlepage.separator">
</xsl:template>
<!--###################################################
Header
################################################### -->
<!-- More space in the center header for long text -->
<xsl:attribute-set name="header.content.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$body.font.family"/>
</xsl:attribute>
<xsl:attribute name="margin-left">-5em</xsl:attribute>
<xsl:attribute name="margin-right">-5em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Custom Footer
################################################### -->
<xsl:template name="footer.content">
<xsl:param name="pageclass" select="''" />
<xsl:param name="sequence" select="''" />
<xsl:param name="position" select="''" />
<xsl:param name="gentext-key" select="''" />
<xsl:variable name="Version">
<xsl:if test="//releaseinfo">
<xsl:text>Spring Web Flow </xsl:text><xsl:value-of select="//releaseinfo" /><xsl:text></xsl:text>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$sequence='blank'">
<xsl:if test="$position = 'center'">
<xsl:value-of select="$Version" />
</xsl:if>
</xsl:when>
<!-- for double sided printing, print page numbers on alternating sides (of the page) -->
<xsl:when test="$double.sided != 0">
<xsl:choose>
<xsl:when test="$sequence = 'even' and $position='left'">
<fo:page-number />
</xsl:when>
<xsl:when test="$sequence = 'odd' and $position='right'">
<fo:page-number />
</xsl:when>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version" />
</xsl:when>
</xsl:choose>
</xsl:when>
<!-- for single sided printing, print all page numbers on the right (of the page) -->
<xsl:when test="$double.sided = 0">
<xsl:choose>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version" />
</xsl:when>
<xsl:when test="$position='right'">
<fo:page-number />
</xsl:when>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<!--###################################################
Custom Toc Line
################################################### -->
<!-- The default DocBook XSL TOC printing is seriously broken... -->
<xsl:template name="toc.line">
<xsl:variable name="id">
<xsl:call-template name="object.id"/>
</xsl:variable>
<xsl:variable name="label">
<xsl:apply-templates select="." mode="label.markup"/>
</xsl:variable>
<!-- justify-end removed from block attributes (space problem in title.markup) -->
<fo:block end-indent="{$toc.indent.width}pt"
last-line-end-indent="-{$toc.indent.width}pt"
white-space-treatment="preserve"
text-align="left"
white-space-collapse="false">
<fo:inline keep-with-next.within-line="always">
<!-- print Chapters in bold style -->
<xsl:choose>
<xsl:when test="local-name(.) = 'chapter'">
<xsl:attribute name="font-weight">bold</xsl:attribute>
</xsl:when>
</xsl:choose>
<fo:basic-link internal-destination="{$id}">
<xsl:if test="$label != ''">
<xsl:copy-of select="$label"/>
<fo:inline white-space-treatment="preserve"
white-space-collapse="false">
<xsl:value-of select="$autotoc.label.separator"/>
</fo:inline>
</xsl:if>
<xsl:apply-templates select="." mode="title.markup"/>
</fo:basic-link>
</fo:inline>
<fo:inline keep-together.within-line="always">
<xsl:text> </xsl:text>
<fo:leader leader-pattern="dots"
leader-pattern-width="3pt"
leader-alignment="reference-area"
keep-with-next.within-line="always"/>
<xsl:text> </xsl:text>
<fo:basic-link internal-destination="{$id}">
<fo:page-number-citation ref-id="{$id}"/>
</fo:basic-link>
</fo:inline>
</fo:block>
</xsl:template>
<!--###################################################
Extensions
################################################### -->
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<!-- FOP provide only PDF Bookmarks at the moment -->
<xsl:param name="fop.extensions">1</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">2</xsl:param>
<!-- Dot and Whitespace as separator in TOC between Label and Title-->
<xsl:param name="autotoc.label.separator" select="'. '"/>
<!--###################################################
Paper & Page Size
################################################### -->
<!-- Paper type, no headers on blank pages, no double sided printing -->
<xsl:param name="paper.type" select="'A4'"/>
<xsl:param name="double.sided">0</xsl:param>
<xsl:param name="headers.on.blank.pages">0</xsl:param>
<xsl:param name="footers.on.blank.pages">0</xsl:param>
<!-- Space between paper border and content (chaotic stuff, don't touch) -->
<xsl:param name="page.margin.top">5mm</xsl:param>
<xsl:param name="region.before.extent">10mm</xsl:param>
<xsl:param name="body.margin.top">10mm</xsl:param>
<xsl:param name="body.margin.bottom">15mm</xsl:param>
<xsl:param name="region.after.extent">10mm</xsl:param>
<xsl:param name="page.margin.bottom">0mm</xsl:param>
<xsl:param name="page.margin.outer">18mm</xsl:param>
<xsl:param name="page.margin.inner">18mm</xsl:param>
<!-- No intendation of Titles -->
<xsl:param name="title.margin.left">0pc</xsl:param>
<!--###################################################
Fonts & Styles
################################################### -->
<!-- Left aligned text and no hyphenation -->
<xsl:param name="alignment">justify</xsl:param>
<xsl:param name="hyphenate">false</xsl:param>
<!-- Default Font size -->
<xsl:param name="body.font.master">11</xsl:param>
<xsl:param name="body.font.small">8</xsl:param>
<!-- Line height in body text -->
<xsl:param name="line-height">1.4</xsl:param>
<!-- Monospaced fonts are smaller than regular text -->
<xsl:attribute-set name="monospace.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$monospace.font.family"/>
</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Tables
################################################### -->
<!-- The table width should be adapted to the paper size -->
<xsl:param name="default.table.width">17.4cm</xsl:param>
<!-- Some padding inside tables -->
<xsl:attribute-set name="table.cell.padding">
<xsl:attribute name="padding-left">4pt</xsl:attribute>
<xsl:attribute name="padding-right">4pt</xsl:attribute>
<xsl:attribute name="padding-top">4pt</xsl:attribute>
<xsl:attribute name="padding-bottom">4pt</xsl:attribute>
</xsl:attribute-set>
<!-- Only hairlines as frame and cell borders in tables -->
<xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
<xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Titles
################################################### -->
<!-- Chapter title size -->
<xsl:attribute-set name="chapter.titlepage.recto.style">
<xsl:attribute name="text-align">left</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.8"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
Let's remove it, so this sucker can use our attribute-set only... -->
<xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsl:use-attribute-sets="chapter.titlepage.recto.style">
<xsl:call-template name="component.title">
<xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
</xsl:call-template>
</fo:block>
</xsl:template>
<!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
<xsl:attribute-set name="section.title.level1.properties">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.5"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level2.properties">
<xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.25"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level3.properties">
<xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!-- Titles of formal objects (tables, examples, ...) -->
<xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="hyphenate">false</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Programlistings
################################################### -->
<!-- Verbatim text formatting (programlistings) -->
<xsl:attribute-set name="monospace.verbatim.properties">
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.small * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="verbatim.properties">
<xsl:attribute name="space-before.minimum">1em</xsl:attribute>
<xsl:attribute name="space-before.optimum">1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">1em</xsl:attribute>
<xsl:attribute name="border-color">#444444</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1pt</xsl:attribute>
<xsl:attribute name="padding-top">0.5em</xsl:attribute>
<xsl:attribute name="padding-left">0.5em</xsl:attribute>
<xsl:attribute name="padding-right">0.5em</xsl:attribute>
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
<xsl:attribute name="margin-left">0.5em</xsl:attribute>
<xsl:attribute name="margin-right">0.5em</xsl:attribute>
</xsl:attribute-set>
<!-- Shade (background) programlistings -->
<xsl:param name="shade.verbatim">1</xsl:param>
<xsl:attribute-set name="shade.verbatim.style">
<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">0</xsl:param>
<xsl:param name="callout.unicode">1</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<xsl:param name="admon.graphics.path">&admon_gfx_path;</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<!-- Format Variable Lists as Blocks (prevents horizontal overflow) -->
<xsl:param name="variablelist.as.blocks">1</xsl:param>
<!-- The horrible list spacing problems -->
<xsl:attribute-set name="list.block.spacing">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
colored and hyphenated links
################################################### -->
<xsl:template match="ulink">
<fo:basic-link external-destination="{@url}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@url"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,277 @@
body {
text-align: justify;
margin-right: 2em;
margin-left: 2em;
}
a,
a[accesskey^="h"],
a[accesskey^="n"],
a[accesskey^="u"],
a[accesskey^="p"] {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
color: #003399;
}
a:active {
color: #003399;
}
a:visited {
color: #888888;
}
p {
font-family: Verdana, Arial;
}
dt {
font-family: Verdana, Arial;
font-size: 12px;
}
p, dl, dt, dd, blockquote {
color: #000000;
margin-bottom: 3px;
margin-top: 3px;
padding-top: 0px;
}
ol, ul, p {
margin-top: 6px;
margin-bottom: 6px;
}
p, blockquote {
font-size: 90%;
}
p.releaseinfo {
font-size: 100%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
padding-top: 10px;
}
p.pubdate {
font-size: 120%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
}
td {
font-size: 80%;
}
td, th, span {
color: #000000;
}
td[width^="40%"] {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
color: #003399;
}
table[summary^="Navigation header"] tbody tr th[colspan^="3"] {
font-family: Verdana, Arial, helvetica, sans-serif;
}
blockquote {
margin-right: 0px;
}
h1, h2, h3, h4, h6, H6 {
color: #000000;
font-weight: 500;
margin-top: 0px;
padding-top: 14px;
font-family: Verdana, Arial, helvetica, sans-serif;
margin-bottom: 0px;
}
h2.title {
font-weight: 800;
margin-bottom: 8px;
}
h2.subtitle {
font-weight: 800;
margin-bottom: 20px;
}
.firstname, .surname {
font-size: 12px;
font-family: Verdana, Arial, helvetica, sans-serif;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 10px 0px 30px 50px;
width: 90%;
}
div.table {
margin: 30px 0px 30px 0px;
border: 1px dashed gray;
padding: 10px;
}
div.table > p.title {
padding-left: 10px;
}
table[summary^="Navigation footer"] {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 0px;
width: 100%;
}
table[summary^="Note"], table[summary^="Warning"], table[summary^="Tip"] {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 10px 0px 10px -20px;
width: 100%;
}
td {
padding: 4pt;
font-family: Verdana, Arial, helvetica, sans-serif;
}
div.warning TD {
text-align: justify;
}
h1 {
font-size: 150%;
}
h2 {
font-size: 110%;
}
h3 {
font-size: 100%; font-weight: bold;
}
h4 {
font-size: 90%; font-weight: bold;
}
h5 {
font-size: 90%; font-style: italic;
}
h6 {
font-size: 100%; font-style: italic;
}
tt {
font-size: 110%;
font-family: "Courier New", Courier, monospace;
color: #000000;
}
.navheader, .navfooter {
border: none;
}
div.navfooter table {
border: dashed gray;
border-width: 1px 1px 1px 1px;
background-color: #cde48d;
}
pre {
font-size: 110%;
padding: 5px;
border-style: solid;
border-width: 1px;
border-color: #CCCCCC;
background-color: #F4F4F4;
}
ul, ol, li {
list-style: disc;
}
hr {
width: 100%;
height: 1px;
background-color: #CCCCCC;
border-width: 0px;
padding: 0px;
}
.variablelist {
padding-top: 10px;
padding-bottom: 10px;
margin: 0;
}
.term {
font-weight:bold;
}
.mediaobject {
padding-top: 30px;
padding-bottom: 30px;
}
.legalnotice {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
font-style: italic;
}
.sidebar {
float: right;
margin: 10px 0px 10px 30px;
padding: 10px 20px 20px 20px;
width: 33%;
border: 1px solid black;
background-color: #F4F4F4;
font-size: 14px;
}
.property {
font-family: "Courier New", Courier, monospace;
}
a code {
font-family: Verdana, Arial;
font-size: 12px;
}
td code {
font-size: 110%;
}
div.note * td,
div.tip * td,
div.warning * td {
text-align: justify;
font-size: 100%;
}
.programlisting .interfacename,
.programlisting .literal,
.programlisting .classname {
font-size: 95%;
}
/* everything in a <lineannotation/> is displayed in a nice green, comment-like color */
.programlisting * .lineannotation,
.programlisting * .lineannotation * {
color: green;
}

View File

@@ -0,0 +1,116 @@
<?xml version="1.0"?>
<!--
This is the XSL HTML configuration file for the Spring
Reference Documentation.
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY db_xsl_path "../lib/docbook-xsl/">
<!ENTITY callout_gfx_path "../images/callouts/">
<!ENTITY admon_gfx_path "../images/admons/">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<xsl:import href="&db_xsl_path;/html/onechunk.xsl"/>
<!--###################################################
HTML Settings
################################################### -->
<xsl:param name="html.stylesheet">styles/html.css</xsl:param>
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">1</xsl:param>
<xsl:param name="callout.graphics.path">&callout_gfx_path;</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<xsl:param name="admon.graphics.path">&admon_gfx_path;</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name" />
<xsl:apply-templates mode="titlepage.mode" select="./contrib" />
<xsl:apply-templates mode="titlepage.mode" select="./affiliation" />
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p/>
<xsl:apply-templates mode="titlepage.mode" />
</div>
</xsl:template>
<!--###################################################
Headers and Footers
################################################### -->
<!-- let's have a Spring banner across the top of each page -->
<xsl:template name="user.header.navigation">
<div style="background-color:white;border:none;height:73px;border:1px solid black;">
<a style="border:none;" href="http://www.springframework.org/" title="The Spring Framework">
<img style="border:none;" src="images/xdev-spring_logo.jpg" />
</a>
</div>
</xsl:template>
<!-- no other header navigation (prev, next, etc.) -->
<xsl:template name="header.navigation" />
<!-- no other footer navigation (prev, next, etc.) -->
<xsl:template name="footer.navigation"/>
</xsl:stylesheet>

View File

@@ -0,0 +1,210 @@
<?xml version="1.0" ?>
<!--
This is the XSL HTML configuration file for the Spring Reference Documentation.
-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY db_xsl_path "../lib/docbook-xsl/">
<!ENTITY callout_gfx_path "../images/callouts/">
<!ENTITY admon_gfx_path "../images/admons/">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="http://www.w3.org/TR/xhtml1/transitional"
exclude-result-prefixes="#default">
<xsl:import href="&db_xsl_path;/html/chunk.xsl" />
<!--###################################################
HTML Settings
################################################### -->
<xsl:param name="chunk.section.depth">'5'</xsl:param>
<xsl:param name="use.id.as.filename">'1'</xsl:param>
<xsl:param name="html.stylesheet">styles/html.css</xsl:param>
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="use.extensions">1</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="callout.extensions">1</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1" />
<xsl:param name="section.label.includes.component.label" select="1" />
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">1</xsl:param>
<xsl:param name="callout.graphics.path">&callout_gfx_path;</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<xsl:param name="admon.graphics.path">&admon_gfx_path;</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name" />
<xsl:apply-templates mode="titlepage.mode" select="./contrib" />
<xsl:apply-templates mode="titlepage.mode" select="./affiliation" />
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p />
<xsl:apply-templates mode="titlepage.mode" />
</div>
</xsl:template>
<!--###################################################
Headers and Footers
################################################### -->
<!-- let's have a Spring banner across the top of each page -->
<xsl:template name="user.header.navigation">
<div style="background-color:white;border:none;height:73px;border:1px solid black;">
<a style="border:none;" href="http://www.springframework.org/" title="The Spring Framework">
<img style="border:none;" src="images/xdev-spring_logo.jpg" />
</a>
</div>
</xsl:template>
<!-- no other header navigation (prev, next, etc.) -->
<xsl:template name="header.navigation" />
<xsl:param name="navig.showtitles">1</xsl:param>
<xsl:template name="footer.navigation">
<xsl:param name="prev" select="/foo" />
<xsl:param name="next" select="/foo" />
<xsl:param name="nav.context" />
<xsl:variable name="home" select="/*[1]" />
<xsl:variable name="up" select="parent::*" />
<xsl:variable name="row1" select="count($prev) &gt; 0
or count($up) &gt; 0
or count($next) &gt; 0" />
<xsl:variable name="row2" select="($prev and $navig.showtitles != 0)
or (generate-id($home) != generate-id(.)
or $nav.context = 'toc')
or ($chunk.tocs.and.lots != 0
and $nav.context != 'toc')
or ($next and $navig.showtitles != 0)" />
<xsl:if test="$suppress.navigation = '0' and $suppress.footer.navigation = '0'">
<div class="navfooter">
<xsl:if test="$footer.rule != 0">
<hr />
</xsl:if>
<xsl:if test="$row1 or $row2">
<table width="100%" summary="Navigation footer">
<xsl:if test="$row1">
<tr>
<td width="40%" align="left">
<xsl:if test="count($prev)>0">
<a accesskey="p">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$prev" />
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'prev'" />
</xsl:call-template>
</a>
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
<xsl:choose>
<xsl:when test="$home != . or $nav.context = 'toc'">
<a accesskey="h">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$home" />
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'home'" />
</xsl:call-template>
</a>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<xsl:text>&#160;|&#160;</xsl:text>
</xsl:if>
</xsl:when>
<xsl:otherwise>&#160;</xsl:otherwise>
</xsl:choose>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<a accesskey="t">
<xsl:attribute name="href">
<xsl:apply-templates select="/*[1]" mode="recursive-chunk-filename">
<xsl:with-param name="recursive" select="true()" />
</xsl:apply-templates>
<xsl:text>-toc</xsl:text>
<xsl:value-of select="$html.ext" />
</xsl:attribute>
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'nav-toc'" />
</xsl:call-template>
</a>
</xsl:if>
</td>
<td width="40%" align="right">
<xsl:text>&#160;</xsl:text>
<xsl:if test="count($next)>0">
<a accesskey="n">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$next" />
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'next'" />
</xsl:call-template>
</a>
</xsl:if>
</td>
</tr>
</xsl:if>
<xsl:if test="$row2">
<tr>
<td width="40%" align="left" valign="top">
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$prev" mode="object.title.markup" />
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
</td>
<td width="40%" align="right" valign="top">
<xsl:text>&#160;</xsl:text>
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$next" mode="object.title.markup" />
</xsl:if>
</td>
</tr>
</xsl:if>
</table>
</xsl:if>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,245 @@
<?xml version="1.0"?>
<!--
Copyright 2002-2006 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Effects the transformation of taglib XML to DocBook XML.
Author: Rick Evans (based on Tim 'katentim' Nolan's original stylesheet)
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan">
<xsl:output
method="xml"
indent="yes"
xalan:indent-amount="3"
omit-xml-declaration="no"/>
<xsl:param name="title"/>
<xsl:template match="taglib">
<xsl:element name="appendix">
<xsl:attribute name="id">
<xsl:value-of select="$title"/>
</xsl:attribute>
<xsl:element name="title"><xsl:value-of select="$title"/></xsl:element>
<xsl:element name="section">
<xsl:attribute name="id">
<xsl:value-of select="$title"/>
<xsl:text>-intro</xsl:text>
</xsl:attribute>
<xsl:element name="title"><xsl:text>Introduction</xsl:text></xsl:element>
</xsl:element>
<xsl:element name="para">
<xsl:text>One of the view technologies you can use with the Spring Framework
is Java Server Pages (JSPs). To help you implement views using Java Server Pages
the Spring Framework provides you with some tags for evaluating errors, setting
themes and outputting internationalized messages.</xsl:text>
</xsl:element>
<xsl:element name="para">
<xsl:text>This appendix describes the </xsl:text>
<xsl:element name="literal">
<xsl:value-of select="$title"/>
</xsl:element>
<xsl:text> tag library.</xsl:text>
</xsl:element>
<xsl:element name="itemizedlist">
<xsl:apply-templates select="tag" mode="mini-toc">
<xsl:sort select="name" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
<xsl:apply-templates select="tag">
<xsl:sort select="name" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="tag" mode="mini-toc">
<xsl:element name="listitem">
<xsl:element name="xref">
<xsl:attribute name="linkend">
<xsl:call-template name="generate.id">
<xsl:with-param name="id">
<xsl:value-of select="./name"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="tag">
<xsl:element name="section">
<xsl:attribute name="id">
<xsl:call-template name="generate.id">
<xsl:with-param name="id">
<xsl:value-of select="./name"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
<xsl:element name="title">
<xsl:text>The </xsl:text>
<xsl:element name="literal">
<xsl:value-of select="./name"/>
</xsl:element>
<xsl:text> tag</xsl:text>
</xsl:element>
<xsl:element name="para">
<xsl:value-of select="./description"/>
</xsl:element>
<xsl:element name="table">
<xsl:attribute name="id">
<xsl:call-template name="generate.id">
<xsl:with-param name="id">
<xsl:value-of select="./name"/>
</xsl:with-param>
</xsl:call-template>
<xsl:text>.table</xsl:text>
</xsl:attribute>
<xsl:element name="title">
<xsl:text>Attributes</xsl:text>
</xsl:element>
<xsl:element name="tgroup">
<xsl:attribute name="cols">
<xsl:text>3</xsl:text>
</xsl:attribute>
<xsl:element name="spanspec">
<xsl:attribute name="spanname">
<xsl:text>description.span</xsl:text>
</xsl:attribute>
<xsl:attribute name="namest">
<xsl:text>Attribute</xsl:text>
</xsl:attribute>
<xsl:attribute name="nameend">
<xsl:text>Runtime.Expression</xsl:text>
</xsl:attribute>
<xsl:attribute name="align">
<xsl:text>left</xsl:text>
</xsl:attribute>
</xsl:element>
<xsl:element name="colspec">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:attribute name="colname">
<xsl:text>Attribute</xsl:text>
</xsl:attribute>
</xsl:element>
<xsl:element name="colspec">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:attribute name="colname">
<xsl:text>Required</xsl:text>
</xsl:attribute>
</xsl:element>
<xsl:element name="colspec">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:attribute name="colname">
<xsl:text>Runtime.Expression</xsl:text>
</xsl:attribute>
</xsl:element>
<xsl:element name="thead">
<xsl:element name="row">
<xsl:element name="entry">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:text>Attribute</xsl:text>
</xsl:element>
<xsl:element name="entry">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:text>Required?</xsl:text>
</xsl:element>
<xsl:element name="entry">
<xsl:attribute name="align">
<xsl:text>center</xsl:text>
</xsl:attribute>
<xsl:text>Runtime Expression?</xsl:text>
</xsl:element>
</xsl:element>
</xsl:element>
<xsl:element name="tbody">
<xsl:apply-templates select="attribute">
<xsl:sort select="name" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="attribute">
<xsl:element name="row">
<xsl:element name="entry">
<xsl:element name="para">
<xsl:value-of select="name"/>
</xsl:element>
</xsl:element>
<xsl:element name="entry">
<xsl:element name="para">
<xsl:value-of select="required"/>
</xsl:element>
</xsl:element>
<xsl:element name="entry">
<xsl:element name="para">
<xsl:value-of select="rtexprvalue"/>
</xsl:element>
</xsl:element>
</xsl:element>
<xsl:element name="row">
<xsl:element name="entry">
<xsl:attribute name="spanname">
<xsl:text>description.span</xsl:text>
</xsl:attribute>
<xsl:element name="para">
<xsl:value-of select="description"/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="attribute/description">
<xsl:element name="row">
<xsl:element name="entry">
<xsl:attribute name="spanname">
<xsl:text>description.span</xsl:text>
</xsl:attribute>
<xsl:element name="para">
<xsl:value-of select="description"/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="generate.id">
<xsl:param name="id"/>
<xsl:value-of select="$title"/>.<xsl:value-of select="$id"/>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0"?>
<!--
Copyright 2002-2006 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!--
Effects the transformation of the various Spring schema definitions to DocBook XML.
Author: Rick Evans
-->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xalan="http://xml.apache.org/xalan">
<xsl:output
method="xml"
indent="yes"
xalan:indent-amount="3"
omit-xml-declaration="no"/>
<xsl:param name="title"/>
<xsl:template match="xsd:schema">
<xsl:element name="appendix">
<xsl:attribute name="id">
<xsl:value-of select="$title"/>
</xsl:attribute>
<xsl:element name="title">
<xsl:element name="literal">
<xsl:value-of select="$title"/>
</xsl:element>
</xsl:element>
<xsl:element name="section">
<xsl:attribute name="id">
<xsl:value-of select="$title"/>
<xsl:text>-intro</xsl:text>
</xsl:attribute>
<xsl:element name="title">
<xsl:text>Introduction</xsl:text>
</xsl:element>
</xsl:element>
<xsl:element name="para">
<xsl:text>This appendix describes the </xsl:text>
<xsl:element name="literal">
<xsl:value-of select="$title"/>
</xsl:element>
<xsl:text> schema.</xsl:text>
</xsl:element>
<xsl:element name="itemizedlist">
<xsl:apply-templates select="xsd:element" mode="mini-toc">
<xsl:sort select="name" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
<xsl:apply-templates select="xsd:element">
<xsl:sort select="name" order="ascending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!--
creates the elements of an <itemizedlist/> containing (hyper)links
to the actual content
-->
<xsl:template match="xsd:element" mode="mini-toc">
<xsl:element name="listitem">
<xsl:element name="xref">
<xsl:attribute name="linkend">
<xsl:call-template name="generate.id">
<xsl:with-param name="id">
<xsl:value-of select="@name"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="xsd:element">
<xsl:element name="section">
<xsl:attribute name="id">
<xsl:call-template name="generate.id">
<xsl:with-param name="id">
<xsl:value-of select="@name"/>
</xsl:with-param>
</xsl:call-template>
</xsl:attribute>
<xsl:element name="title">
<xsl:text>The </xsl:text>
<xsl:element name="literal">
<xsl:value-of select="@name"/>
</xsl:element>
<xsl:text> element</xsl:text>
</xsl:element>
<xsl:element name="para">
<xsl:text>[TODO : insert the description of the element here]</xsl:text>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="generate.id">
<xsl:param name="id"/>
<xsl:value-of select="$title"/>.<xsl:value-of select="$id"/>
</xsl:template>
</xsl:stylesheet>