Moved Spring Web Flow to a top level project
2
spring-webflow/docs/reference/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
lib
|
||||
target
|
||||
BIN
spring-webflow/docs/reference/images/admons/blank.png
Normal file
|
After Width: | Height: | Size: 374 B |
BIN
spring-webflow/docs/reference/images/admons/caution.gif
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
spring-webflow/docs/reference/images/admons/caution.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
spring-webflow/docs/reference/images/admons/caution.tif
Normal file
BIN
spring-webflow/docs/reference/images/admons/draft.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
spring-webflow/docs/reference/images/admons/home.gif
Normal file
|
After Width: | Height: | Size: 321 B |
BIN
spring-webflow/docs/reference/images/admons/home.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/important.gif
Normal file
|
After Width: | Height: | Size: 1003 B |
BIN
spring-webflow/docs/reference/images/admons/important.png
Normal file
|
After Width: | Height: | Size: 722 B |
BIN
spring-webflow/docs/reference/images/admons/important.tif
Normal file
BIN
spring-webflow/docs/reference/images/admons/next.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/next.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/note.gif
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
spring-webflow/docs/reference/images/admons/note.png
Normal file
|
After Width: | Height: | Size: 490 B |
BIN
spring-webflow/docs/reference/images/admons/note.tif
Normal file
BIN
spring-webflow/docs/reference/images/admons/prev.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/prev.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/tip.gif
Normal file
|
After Width: | Height: | Size: 598 B |
BIN
spring-webflow/docs/reference/images/admons/tip.png
Normal file
|
After Width: | Height: | Size: 449 B |
BIN
spring-webflow/docs/reference/images/admons/tip.tif
Normal file
BIN
spring-webflow/docs/reference/images/admons/toc-blank.png
Normal file
|
After Width: | Height: | Size: 318 B |
BIN
spring-webflow/docs/reference/images/admons/toc-minus.png
Normal file
|
After Width: | Height: | Size: 259 B |
BIN
spring-webflow/docs/reference/images/admons/toc-plus.png
Normal file
|
After Width: | Height: | Size: 264 B |
BIN
spring-webflow/docs/reference/images/admons/up.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/up.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
spring-webflow/docs/reference/images/admons/warning.gif
Normal file
|
After Width: | Height: | Size: 743 B |
BIN
spring-webflow/docs/reference/images/admons/warning.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
spring-webflow/docs/reference/images/admons/warning.tif
Normal file
BIN
spring-webflow/docs/reference/images/callouts/1.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/1.png
Normal file
|
After Width: | Height: | Size: 329 B |
BIN
spring-webflow/docs/reference/images/callouts/10.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/10.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
spring-webflow/docs/reference/images/callouts/11.gif
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
spring-webflow/docs/reference/images/callouts/11.png
Normal file
|
After Width: | Height: | Size: 565 B |
BIN
spring-webflow/docs/reference/images/callouts/12.gif
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
spring-webflow/docs/reference/images/callouts/12.png
Normal file
|
After Width: | Height: | Size: 617 B |
BIN
spring-webflow/docs/reference/images/callouts/13.gif
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
spring-webflow/docs/reference/images/callouts/13.png
Normal file
|
After Width: | Height: | Size: 623 B |
BIN
spring-webflow/docs/reference/images/callouts/14.gif
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
spring-webflow/docs/reference/images/callouts/14.png
Normal file
|
After Width: | Height: | Size: 411 B |
BIN
spring-webflow/docs/reference/images/callouts/15.gif
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
spring-webflow/docs/reference/images/callouts/15.png
Normal file
|
After Width: | Height: | Size: 640 B |
BIN
spring-webflow/docs/reference/images/callouts/2.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/2.png
Normal file
|
After Width: | Height: | Size: 353 B |
BIN
spring-webflow/docs/reference/images/callouts/3.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/3.png
Normal file
|
After Width: | Height: | Size: 350 B |
BIN
spring-webflow/docs/reference/images/callouts/4.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/4.png
Normal file
|
After Width: | Height: | Size: 345 B |
BIN
spring-webflow/docs/reference/images/callouts/5.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/5.png
Normal file
|
After Width: | Height: | Size: 348 B |
BIN
spring-webflow/docs/reference/images/callouts/6.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/6.png
Normal file
|
After Width: | Height: | Size: 355 B |
BIN
spring-webflow/docs/reference/images/callouts/7.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/7.png
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
spring-webflow/docs/reference/images/callouts/8.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/8.png
Normal file
|
After Width: | Height: | Size: 357 B |
BIN
spring-webflow/docs/reference/images/callouts/9.gif
Normal file
|
After Width: | Height: | Size: 968 B |
BIN
spring-webflow/docs/reference/images/callouts/9.png
Normal file
|
After Width: | Height: | Size: 357 B |
20
spring-webflow/docs/reference/readme.txt
Normal 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.
|
||||
2461
spring-webflow/docs/reference/src/flow-definition.xml
Normal file
247
spring-webflow/docs/reference/src/flow-execution-repository.xml
Normal 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>
|
||||
809
spring-webflow/docs/reference/src/flow-execution.xml
Normal 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>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<flow xmlns="http://www.springframework.org/schema/webflow"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/webflow
|
||||
http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
|
||||
|
||||
<start-state idref="enterCriteria"/>
|
||||
|
||||
<view-state id="enterCriteria" view="searchCriteria">
|
||||
<render-actions>
|
||||
<action bean="formAction" method="setupForm"/>
|
||||
</render-actions>
|
||||
<transition on="search" to="displayResults">
|
||||
<action bean="formAction" method="bindAndValidate"/>
|
||||
</transition>
|
||||
</view-state>
|
||||
|
||||
<view-state id="displayResults" view="searchResults">
|
||||
<render-actions>
|
||||
<bean-action bean="phonebook" method="search">
|
||||
<method-arguments>
|
||||
<argument expression="flowScope.searchCriteria"/>
|
||||
</method-arguments>
|
||||
<method-result name="results"/>
|
||||
</bean-action>
|
||||
</render-actions>
|
||||
<transition on="newSearch" to="enterCriteria"/>
|
||||
<transition on="select" to="browseDetails"/>
|
||||
</view-state>
|
||||
|
||||
<subflow-state id="browseDetails" flow="detail-flow">
|
||||
<attribute-mapper>
|
||||
<input-mapper>
|
||||
<mapping source="requestParameters.id" target="id" from="string" to="long"/>
|
||||
</input-mapper>
|
||||
</attribute-mapper>
|
||||
<transition on="finish" to="displayResults"/>
|
||||
</subflow-state>
|
||||
|
||||
</flow>
|
||||
</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>
|
||||
555
spring-webflow/docs/reference/src/flow-executor.xml
Normal 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>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns: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">
|
||||
|
||||
<!-- Launches new flow executions and resumes existing executions. -->
|
||||
<flow:executor id="flowExecutor" registry-ref="flowRegistry"/>
|
||||
|
||||
<!-- Creates the registry of flow definitions for this application -->
|
||||
<flow:registry id="flowRegistry">
|
||||
<flow:location path="/WEB-INF/flows/**/*-flow.xml"/>
|
||||
</flow:registry>
|
||||
|
||||
</beans>
|
||||
</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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation">
|
||||
<flow:execution-attributes>
|
||||
<flow:alwaysRedirectOnPause value="false"/>
|
||||
<flow:attribute name="foo" value="bar"/>
|
||||
</flow:execution-attributes>
|
||||
</flow-executor>
|
||||
</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>
|
||||
<flow:executor id="flowExecutor" registry-ref="flowRegistry" repository-type="continuation">
|
||||
<flow:execution-listeners>
|
||||
<flow:listener ref="listener" criteria="order-flow"/>
|
||||
</flow:execution-listeners>
|
||||
</flow-executor>
|
||||
|
||||
<!-- A FlowExecutionListener to observe the lifecycle of order-flow executions -->
|
||||
<bean id="listener" class="org.springframework.webflow.samples.sellitem.SellItemFlowExecutionListener"/>
|
||||
</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>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
|
||||
"http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
<beans>
|
||||
|
||||
<!-- Launches new flow executions and resumes existing executions: Spring 1.2 config version -->
|
||||
<bean id="flowExecutor" class="org.springframework.webflow.config.FlowExecutorFactoryBean">
|
||||
<property name="definitionLocator" ref="flowRegistry"/>
|
||||
<property name="executionAttributes">
|
||||
<map>
|
||||
<entry key="alwaysRedirectOnPause">
|
||||
<value type="java.lang.Boolean">false</value>
|
||||
</entry>
|
||||
</map>
|
||||
</property>
|
||||
<property name="repositoryType" value="CONTINUATION"/>
|
||||
</bean>
|
||||
|
||||
<!-- Creates the registry of flow definitions for this application: Spring 1.2 config version -->
|
||||
<bean id="flowRegistry"
|
||||
class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean">
|
||||
<property name="flowLocations">
|
||||
<list>
|
||||
<value>/WEB-INF/flows/**/*-flow.xml</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
</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>
|
||||
<bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController">
|
||||
<property name="flowExecutor" ref="flowExecutor"/>
|
||||
</bean>
|
||||
</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>
|
||||
<bean id="portletModeControllerMapping"
|
||||
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
|
||||
<property name="portletModeMap">
|
||||
<map>
|
||||
<entry key="view" value-ref="flowController"/>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="flowController" class="org.springframework.webflow.executor.mvc.PortletFlowController">
|
||||
<property name="flowExecutor" ref="flowExecutor"/>
|
||||
<property name="defaultFlowId" ref="search-flow"/>
|
||||
</bean>
|
||||
</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>
|
||||
<a href="flowController.htm?_flowId=myflow">Launch My Flow</a>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-launch-post">
|
||||
<title>Launching a flow execution - form</title>
|
||||
<programlisting>
|
||||
<form action="flowController.htm" method="post">
|
||||
<input type="submit" value="Launch My Flow"/>
|
||||
<input type="hidden" name="_flowId" value="myflow">
|
||||
</form>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-resume-anchor">
|
||||
<title>Resuming a flow execution - anchor</title>
|
||||
<programlisting>
|
||||
<a href="flowController.htm?_flowExecutionKey=${flowExecutionKey}&_eventId=submit">
|
||||
Submit
|
||||
</a>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-resume-form">
|
||||
<title>Resuming a flow execution - form</title>
|
||||
<programlisting>
|
||||
<form action="flowController.htm" method="post">
|
||||
...
|
||||
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
|
||||
<input type="hidden" name="_eventId" value="submit"/>
|
||||
<input type="submit" class="button" value="Submit">
|
||||
</form>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-resume-form-buttons">
|
||||
<title>Resuming a flow execution - multiple form buttons</title>
|
||||
<programlisting>
|
||||
<form action="flowController.htm" method="post">
|
||||
...
|
||||
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
|
||||
<input type="submit" class="button" name="_eventId_submit" value="Submit">
|
||||
<input type="submit" class="button" name="_eventId_cancel" value="Cancel">
|
||||
</form>
|
||||
</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>
|
||||
<a href="flowController.htm?_flowExecutionKey=${flowExecutionKey}">Refresh</a>
|
||||
</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>
|
||||
<bean name="/flowController.htm" class="org.springframework.webflow.executor.mvc.FlowController">
|
||||
<property name="flowExecutor" ref="flowExecutor"/>
|
||||
<property name="argumentHandler">
|
||||
<bean class="org.springframework.webflow.executor.support.RequestPathFlowExecutorArgumentHandler"/>
|
||||
</property>
|
||||
</bean>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-launch-get-rest">
|
||||
<title>Launching a flow execution - REST-style anchor</title>
|
||||
<programlisting>
|
||||
<a href="flowController/myflow"/>Launch My Flow</a>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-resume-form-buttons-requestpath">
|
||||
<title>Resuming a flow execution - multiple form buttons</title>
|
||||
<programlisting>
|
||||
<form action="${flowExecutionKey}" method="post">
|
||||
...
|
||||
<input type="submit" class="button" name="_eventId_submit" value="Submit">
|
||||
<input type="submit" class="button" name="_eventId_cancel" value="Cancel">
|
||||
</form>
|
||||
</programlisting>
|
||||
</sect3>
|
||||
<sect3 id="executor-mvc-refresh-requestpath">
|
||||
<title>Refreshing a flow execution</title>
|
||||
<programlisting>
|
||||
<a href="flowController/k/${flowExecutionKey}">Refresh</a>
|
||||
</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>
|
||||
<form-beans>
|
||||
<form-bean name="actionForm" type="org.springframework.web.struts.SpringBindingActionForm"/>
|
||||
</form-beans>
|
||||
|
||||
<action-mappings>
|
||||
<action path="/flowAction" name="actionForm" scope="request"
|
||||
type="org.springframework.webflow.executor.struts.FlowAction"/>
|
||||
</action-mappings>
|
||||
</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>
|
||||
<faces-config>
|
||||
<application>
|
||||
<navigation-handler>
|
||||
org.springframework.webflow.executor.jsf.FlowNavigationHandler
|
||||
</navigation-handler>
|
||||
<property-resolver>
|
||||
org.springframework.webflow.executor.jsf.FlowPropertyResolver
|
||||
</property-resolver>
|
||||
<variable-resolver>
|
||||
org.springframework.webflow.executor.jsf.FlowVariableResolver
|
||||
</variable-resolver>
|
||||
<variable-resolver>
|
||||
org.springframework.web.jsf.DelegatingVariableResolver
|
||||
</variable-resolver>
|
||||
<variable-resolver>
|
||||
org.springframework.web.jsf.WebApplicationContextVariableResolver
|
||||
</variable-resolver>
|
||||
</application>
|
||||
|
||||
<lifecycle>
|
||||
<phase-listener>org.springframework.webflow.executor.jsf.FlowPhaseListener</phase-listener>
|
||||
</lifecycle>
|
||||
</faces-config>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="executor-jsf-launch-get">
|
||||
<title>Launching a flow execution - command link</title>
|
||||
<programlisting>
|
||||
<h:commandLink value="Go" action="flowId:myflow"/>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="executor-jsf-resume-form">
|
||||
<title>Resuming a flow execution - form</title>
|
||||
<programlisting>
|
||||
<h:form id="form">
|
||||
...
|
||||
<h:inputText id="propertyName" value="#{flowScope.managedBeanName.propertyName}"/>
|
||||
...
|
||||
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
|
||||
<h:commandButton type="submit" value="Next" action="submit"/>
|
||||
</h:form>
|
||||
</programlisting>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 20 KiB |
BIN
spring-webflow/docs/reference/src/images/flow-search.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
BIN
spring-webflow/docs/reference/src/images/junit-greenbar.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
spring-webflow/docs/reference/src/images/logo-ervacon.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
spring-webflow/docs/reference/src/images/logo-interface21.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
spring-webflow/docs/reference/src/images/logo.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
BIN
spring-webflow/docs/reference/src/images/xdev-spring_logo.jpg
Normal file
|
After Width: | Height: | Size: 36 KiB |
79
spring-webflow/docs/reference/src/index.xml
Normal 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>
|
||||
646
spring-webflow/docs/reference/src/overview.xml
Normal 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>
|
||||
47
spring-webflow/docs/reference/src/practical.xml
Normal 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>
|
||||
475
spring-webflow/docs/reference/styles/fopdf.xsl
Normal 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 "©">
|
||||
]>
|
||||
|
||||
<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 ©right; 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>
|
||||
277
spring-webflow/docs/reference/styles/html.css
Normal 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;
|
||||
}
|
||||
116
spring-webflow/docs/reference/styles/html.xsl
Normal 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>
|
||||
210
spring-webflow/docs/reference/styles/html_chunk.xsl
Normal 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) > 0
|
||||
or count($up) > 0
|
||||
or count($next) > 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> </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> | </xsl:text>
|
||||
</xsl:if>
|
||||
</xsl:when>
|
||||
<xsl:otherwise> </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> </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> </xsl:text>
|
||||
</td>
|
||||
<td width="20%" align="center">
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top">
|
||||
<xsl:text> </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>
|
||||
245
spring-webflow/docs/reference/styles/tld.to.docbook.xsl
Normal 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>
|
||||
123
spring-webflow/docs/reference/styles/xsd.to.docbook.xsl
Normal 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>
|
||||