Files
spring-webflow/spring-webflow-reference/src/flow-inheritance.xml
2008-04-15 13:02:21 +00:00

190 lines
6.8 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="flow-inheritance">
<title>Flow Inheritance</title>
<sect1 id="flow-inheritance-introduction">
<title>Introduction</title>
<para>
Flow inheritance allows one flow to inherit the configuration of another flow.
Inheritance can occur at both the flow and state levels.
A common use case is for a parent flow to define global transitions and exception handlers, then each child flow can inherit those settings.
</para>
<para>
In order for a parent flow to be found, it must be added to the <code>flow-registry</code> just like any other flow.
</para>
</sect1>
<sect1 id="flow-inheritance-java-comparison">
<title>Is flow inheritance like Java inheritance?</title>
<para>
Flow inheritance is similar to Java inheritance in that elements defined in a parent are exposed via the child, however, there are key differences.
</para>
<para>
A child flow cannot override an element from a parent flow.
Similar elements between the parent and child flows will be merged.
Unique elements in the parent flow will be added to the child.
</para>
<para>
A child flow can inherit from multiple parent flows.
Java inheritance is limited to a single class.
</para>
</sect1>
<sect1 id="flow-inheritance-levels">
<title>Types of Flow Inheritance</title>
<sect2 id="flow-inheritance-level-flow">
<title>Flow level inheritance</title>
<para>
Flow level inheritance is defined by the <code>parent</code> attribute on the <code>flow</code> element.
The attribute contains a comma separated list of flow identifiers to inherit from.
The child flow will inherit from each parent in the order it is listed adding elements and content to the resulting flow.
The resulting flow from the first merge will be considered the child in the second merge, and so on.
</para>
<programlisting language="xml"><![CDATA[
<flow parent="common-transitions, common-states">]]>
</programlisting>
</sect2>
<sect2 id="flow-inheritance-level-state">
<title>State level inheritance</title>
<para>
State level inheritance is similar to flow level inheritance, except only one state inherits from the parent, instead of the entire flow.
</para>
<para>
Unlike flow inheritance, only a single parent is allowed.
Additionally, the identifier of the flow state to inherit from must also be defined.
The identifiers for the flow and the state within that flow are separated by a #.
</para>
<para>
The parent and child states must be of the same type.
For instance a view-state cannot inherit from an end-state, only another view-state.
</para>
<programlisting language="xml"><![CDATA[
<view-state id="child-state" parent="parent-flow#parent-view-state">]]>
</programlisting>
</sect2>
</sect1>
<sect1 id="flow-inheritance-abstract">
<title>Abstract flows</title>
<para>
Often parent flows are not designed to be executed directly.
In order to protect these flow from running, they can be marked as <code>abstract</code>.
If an abstract flow attempts to run, a <code>FlowBuilderException</code> will be thrown.
</para>
<programlisting language="xml"><![CDATA[
<flow abstract="true">]]>
</programlisting>
</sect1>
<sect1 id="flow-inheritance-algorithm">
<title>Inheritance Algorithm</title>
<para>
When a child flow inherits from it's parent, essentially what happens is that the parent and child are merged together to create a new flow.
There are rules for every element in the Web Flow definition language that govern how that particular element is merged.
</para>
<para>
There are two types of elements mergeable and non-mergeable.
Mergeable elements will always attempt to merge together if the elements are similar.
Non-mergeable elements in a parent or child flow will always be contained in the resulting flow intact.
They will not be modified as part of the merge process.
</para>
<note>
Paths to external resources in the parent flow should be absolute.
Relative paths will break when the two flows are merged unless the parent and child flow are in the same directory.
Once merged, all relative paths in the parent flow will become relative to the child flow.
</note>
<sect2 id="flow-inheritance-algorithm-mergeable">
<title>Mergeable Elements</title>
<para>
If the elements are of the same type and the keyed attribute are identical, the content of the parent element will be merged with the child element.
The merge algorithm will continue to merge each sub-element of the merging parent and child.
Otherwise the parent element is added as a new element to the child.
</para>
<para>
In most cases, elements from a parent flow that are added will be added after elements in the child flow.
Exceptions to this rule include actions elements (evaluate, render and set) which will be added at the beginning.
This allows for the results of parent actions to be used by child actions.
</para>
<para>
Mergeable elements are:
<itemizedlist>
<listitem>
<para>action-state: id</para>
</listitem>
<listitem>
<para>attribute: name</para>
</listitem>
<listitem>
<para>decision-state: id</para>
</listitem>
<listitem>
<para>end-state: id</para>
</listitem>
<listitem>
<para>flow: always merges</para>
</listitem>
<listitem>
<para>if: test</para>
</listitem>
<listitem>
<para>on-end: always merges</para>
</listitem>
<listitem>
<para>on-entry: always merges</para>
</listitem>
<listitem>
<para>on-exit: always merges</para>
</listitem>
<listitem>
<para>on-render: always merges</para>
</listitem>
<listitem>
<para>on-start: always merges</para>
</listitem>
<listitem>
<para>input: name</para>
</listitem>
<listitem>
<para>output: name</para>
</listitem>
<listitem>
<para>secured: attributes</para>
</listitem>
<listitem>
<para>subflow-state: id</para>
</listitem>
<listitem>
<para>transition: on</para>
</listitem>
<listitem>
<para>view-state: id</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2 id="flow-inheritance-nonmergeable">
<title>Non-mergeable Elements</title>
<para>
Non-mergeable elements are:
<itemizedlist>
<listitem>
<para>bean-import</para>
</listitem>
<listitem>
<para>evaluate</para>
</listitem>
<listitem>
<para>exception-handler</para>
</listitem>
<listitem>
<para>persistence-context</para>
</listitem>
<listitem>
<para>render</para>
</listitem>
<listitem>
<para>set</para>
</listitem>
<listitem>
<para>var</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>
</chapter>