diff --git a/spring-webflow/docs/reference/src/flow-executor.xml b/spring-webflow/docs/reference/src/flow-executor.xml
index ed8089e7..59b0b764 100644
--- a/spring-webflow/docs/reference/src/flow-executor.xml
+++ b/spring-webflow/docs/reference/src/flow-executor.xml
@@ -521,74 +521,28 @@
Java Server Faces (JSF) integration
- 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. In addition, it relies on custom Variable and Property Resolvers to
- access flow execution variables from JSF components.
+ Spring Web Flow provides strong integration with Java Server Faces (JSF). When used with JSF, Spring Web Flow
+ takes responsibility for view navigation handling and managing model state, adding power and
+ simplicity to JSF's default navigation system and object scopes. Plain JSF views and components continue to work just as before,
+ and are able to participate in flows with full access to flow state. In addition, other view technologies
+ such as Facelets and Ajax4JSF continue to plug-in normally.
+
+
+ The JSF integration relies on custom implementations of core JSF artifacts such as the PhaseListener
+ and NavigationHandler to drive the execution of flows. In addition, it relies on a custom VariableResolver to
+ access flow execution attributes from JSF components.
- A typical faces-config.xml file
-
-<faces-config>
- <application>
- <navigation-handler>
- org.springframework.webflow.executor.jsf.FlowNavigationHandler
- </navigation-handler>
- <variable-resolver>
- org.springframework.webflow.executor.jsf.FlowExecutionVariableResolver
- </variable-resolver>
- <property-resolver>
- org.springframework.webflow.executor.jsf.FlowExecutionPropertyResolver
- </property-resolver>
- </application>
-
- <lifecycle>
- <phase-listener>org.springframework.webflow.executor.jsf.FlowPhaseListener</phase-listener>
- </lifecycle>
-</faces-config>
-
-
-
- Launching a flow execution - command link
-
- <h:commandLink value="Go" action="flowId:myflow"/>
-
-
-
- Resuming a flow execution - form bound to flow execution variables
-
- <h:form id="form">
- ...
- <h:inputText id="propertyName" value="#{flowExecution.flashScope.aFlashScopeAttribute}"/>
- <h:inputText id="propertyName" value="#{flowExecution.flowScope.aFlowScopeAttribute}"/>
- <h:inputText id="propertyName" value="#{flowExecution.conversationScope.aConversationScopeAttribute}"/>
-
- <h:inputText id="propertyName" value="#{flowExecution.anAttributeToSearchForAcrossAllScopes}"/>
- ...
- <input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
- <h:commandButton type="submit" value="Next" action="submit"/>
- </h:form>
-
-
-
- A pre Spring Web Flow 1.0.2 faces-config.xml file
+ A minimal faces-config.xml file
- Before Spring Web Flow 1.0.2 Spring Web Flow only supported resolving variables in flow scope
- (and not the other scopes such as flash and conversation shown above). This configuration is still supported
- for backwards compatibility reasons and follows:
+ Using Spring Web Flow in a JSF environment requires adding these custom artifacts to the application's
+ faces-config.xml file:
<faces-config>
<application>
- <navigation-handler>
- org.springframework.webflow.executor.jsf.FlowNavigationHandler
- </navigation-handler>
- <variable-resolver>
- org.springframework.webflow.executor.jsf.FlowVariableResolver
- </variable-resolver>
- <property-resolver>
- org.springframework.webflow.executor.jsf.FlowPropertyResolver
- </property-resolver>
+ <navigation-handler>org.springframework.webflow.executor.jsf.FlowNavigationHandler</navigation-handler>
+ <variable-resolver>org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver</variable-resolver>
</application>
<lifecycle>
@@ -596,10 +550,158 @@
</lifecycle>
</faces-config>
+
+ The FlowPhaseListener is required to manage the overall flow execution lifecycle in a JSF environment. It handles launching new
+ flows accessed by browsers via direct URLs, and also handles restoring flow executions on postback and browser refreshes.
+
+
+ The FlowNavigationHandler is required to continue a flow on an action outcome from a JSF view
+ participating in the flow. Outcome strings are treated as events signaled against the current view state
+ of the flow execution automatically.
+
+
+ The DelegatingFlowVariableResolver resolves JSF a value binding expression like {#someBean.someProperty}
+ to a flow execution attribute. This resolver searches flash, flow, and conversation scope in that order until
+ it finds a match. If no match is found this resolver delegates to the next resolver in the chain.
+
+
+
+ Launching a flow execution - JSF command link component
+
+ Flows can be launched by firing JSF action outcomes that adhere to a special format:
+
+
+ <h:commandLink value="Go" action="flowId:myflow"/>
+
+
+ The command link above says launch 'myflow' when clicked.
+ By default, an action outcome prefixed with flowId: will treated as a flow definition identifier.
+ The FlowNavigationHandler will launch a new execution of that flow definition.
+
+
+ The flow id prefix respected by the FlowNavigationHandler is configurable. See the API documentation for
+ more information.
+
+
+
+ Launching a flow execution - normal HTML anchor
+
+ Flows can also be launched simply by accessing flow definition URLs directly using a bookmark or normal HTML link:
+
+
+ <a href="app.faces?flowId=myflow">Go</a>
+
+
+ This example link assumes *.faces has been mapped to the FacesServlet defined within web.xml.
+ The format of a flow definition URL is configurable on the FlowPhaseListener.
+
+
+
+ Sample flow in a JSF environment
+
+ Flow definitions in a JSF environment are just plain Spring Web Flow definitions:
+
+
+<?xml version="1.0" encoding="UTF-8"?>
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow
+ http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
+
+ <var name="bean" class="example.ManagedBeanImpl" scope="conversation" />
+
+ <start-state idref="displayView" />
+
+ <view-state id="displayView" view="/myview.jsp">
+ <transition on="submit" to="displayNextView"/>
+ </view-state>
+
+ <view-state id="displayNextView" view="/nextview.jsp" />
+
+</flow>
+
+
+ A benefit of using JSF is UI components typically handle data binding and validation, so the actual flow
+ definition logic is often simpler and more focused. In general, it is recommended views selected by
+ view states follow the standard JSF view identifier format, which requires a leading forward-slash
+ and ends in a prefix.
+
+
+ How Spring Web Flow view names are mapped to JSF view ids is configurable. See the
+ FlowPhaseListener API documentation for more information.
+
+
+
+ Resuming a flow execution - form bound to flow execution variables
+
+ Views participating in flows are just plain JSF views. They may also incorporate other
+ JSF view technologies such as Facelets and Ajax4JSF.
+
+
+<f:view>
+ <h:form id="form">
+ ...
+ <h:inputText id="propertyName" value="#{someBean.someProperty}"/>
+ ...
+ <h:commandButton type="submit" value="Next" action="submit"/>
+ </h:form>
+</f:view>
+
+
+ As shown above, there is nothing Spring Web Flow specific here. The flow execution
+ key is automatically tracked by a special UI component in the view root, so there is no need to
+ track it manually. Action outcomes are automatically mapped to Spring Web Flow event identifiers
+ signaled against the current state.
+
+
+
+ Spring Web Flow JSF Integration Samples
+
+ See the sellitem-jsf sample that illustrates Spring Web Flow operating in
+ a JSF environment.
+
+
+
+ A pre Spring Web Flow 1.0.2 faces-config.xml file
+
+ This section applies to those using Spring Web Flow's JSF integration before release 1.0.2.
+
+
+ Before release 1.0.2, Spring Web Flow only supported resolving variables in flow scope
+ (and not the other scopes such as flash and conversation shown above). This configuration is still supported
+ for backwards compatibility reasons:
+
+
+<faces-config>
+ <application>
+ <navigation-handler>org.springframework.webflow.executor.jsf.FlowNavigationHandler</navigation-handler>
+ <variable-resolver>org.springframework.webflow.executor.jsf.FlowVariableResolver</variable-resolver>
+ <property-resolver>org.springframework.webflow.executor.jsf.FlowPropertyResolver</property-resolver>
+ </application>
+
+ <lifecycle>
+ <phase-listener>org.springframework.webflow.executor.jsf.FlowPhaseListener</phase-listener>
+ </lifecycle>
+</faces-config>
+
+
+
+ With 1.0.2 DelegatingFlowVariableResolver is now the recommended default resolver,
+ as it allows full access to all flow execution scopes transparently from the point of view of the
+ JSF view developer.
+
+
- Resuming a flow execution - pre 1.0.2 form bound to flow scope variables
+ Resuming a flow execution - pre Spring Web Flow 1.0.2
+
+ Before release 1.0.2, the flow execution key had to be tracked manually in JSF views participating
+ in a flow execution. This configuration is still supported for backwards compatibility reasons.
+ However, it is highly recommended that existing users of Spring Web Flow's JSF integration
+ update their views to be just plain JSF.
+
+<f:view>
<h:form id="form">
...
<h:inputText id="propertyName" value="#{flowScope.aFlowScopeAttribute}"/>
@@ -607,7 +709,12 @@
<input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}">
<h:commandButton type="submit" value="Next" action="submit"/>
</h:form>
+</f:view>
+
+ The hidden form field above can now be safely removed. In addition, the new variable resolver
+ can be plugged in to gain access to other scopes such as flash and conversation.
+
\ No newline at end of file
diff --git a/spring-webflow/docs/reference/src/practical.xml b/spring-webflow/docs/reference/src/practical.xml
index 76db2c50..090c9995 100644
--- a/spring-webflow/docs/reference/src/practical.xml
+++ b/spring-webflow/docs/reference/src/practical.xml
@@ -1766,8 +1766,8 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
Overview
The Sellitem-JSF example uses Web Flow and JSF to build a shopping
- cart wizard. Navigation logic and supporting "flow" scoped beans
- are supplied through Spring and Spring Web Flow while JSP's and
+ cart wizard. Navigation logic and supporting managed beans
+ are supplied by Spring Web Flow while UI views and
overall servlet processing is based on JSF technology.
@@ -1785,7 +1785,7 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
Web.xml
The web.xml contains standard JSF configuration including mappings for
- the JSF front servlet: it handles all requests ending with "*.jsf":
+ the JSF front servlet: it handles all requests ending with "*.faces":
<!-- Faces Servlet -->
<servlet>
@@ -1796,13 +1796,13 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
- <url-pattern>*.jsf</url-pattern>
+ <url-pattern>*.faces</url-pattern>
</servlet-mapping>
- In addition the web.xml loads to Spring contexts with the
- ContextLoaderListener:
+ In addition the web.xml loads a Spring root web application context containing the services
+ used by the application:
<context-param>
<param-name>contextConfigLocation</param-name>
@@ -1819,29 +1819,23 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
The services-config.xml contains POJO beans required for the services and
data access layers of the application. These declarations are very similar
to the Sellitem example (and explained in more detail there).
- The webflow-config.xml context contains Web Flow related bean
+ The webflow-config.xml contains Web Flow related bean
definitions. These definitions will be explained a little bit
further on in the context of how they fit into the JSF phases
lifecycle.
- JSF Setup in faces-config.xml
+ Web Flow JSF Setup in faces-config.xml
- The Spring framework has several classes to help JSF applications
- to use Spring beans as JSF managed beans and to do dependency injection
- on a navigation handler or a phase listener using Spring.
+ To plug in Web Flow a few things must be added once to faces-config.xml.
This is demonstrated in the faces-config.xml of Sellitem-JSF:
<application>
- <!-- Navigation handler proxy for a Spring-managed bean that is the Web Flow Navigation Handler -->
- <navigation-handler>
- org.springframework.webflow.executor.jsf.FlowNavigationHandler
- </navigation-handler>
- <variable-resolver>
- org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver
- </variable-resolver>
+ <navigation-handler>org.springframework.webflow.executor.jsf.FlowNavigationHandler</navigation-handler>
+ <variable-resolver>org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver</variable-resolver>
</application>
+
<lifecycle>
<phase-listener>org.springframework.webflow.executor.jsf.FlowPhaseListener</phase-listener>
</lifecycle>
@@ -1866,27 +1860,35 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
- Web Flow Definitions
+ Web Flow System Setup in webflow-config.xml
Examining the definitions in faces-config.xml highlighted the ability
- to use Spring beans as JSF managed beans as well as plug Web Flow
- definitions for JSF navigation logic. Now we can turn to the question
- of how to configure specific web flow definitions.
+ to use plug Web Flow in as a navigation handler and as a source
+ for JSF managed beans. Now we can turn to the question
+ of how to configure the web flow system itself in a JSF environment.
- The Spring web context /WEB-INF/webflow-config.xml contains the following
- flow registry bean definition:
+ The Spring web context fragment /WEB-INF/webflow-config.xml contains the following configuration:
+<!-- Launches new flow executions and resumes existing executions -->
+<flow:executor id="flowExecutor" registry-ref="flowRegistry" />
+
<!-- Creates the registry of flow definitions for this application -->
-<flow:registry id="flowDefinitionLocator">
+<flow:registry id="flowRegistry">
<flow:location path="/WEB-INF/flows/sellitem-flow.xml" />
</flow:registry>
- Here the flow registry definies the path to one web flow definition -
- sellitem-flow.xml. The flow registry bean with an id of "flowDefinitionLocator"
- is accessed by the FlowPhaseListener, which makes the specified web flow
- definitions available for use in JSF. The intro.jsp page shows how the
- configured web flow sellitem-flow.xml can be invoked:
+ Here the flow executor is configured to support execution of a single
+ flow definition - sellitem-flow.xml. The executor bean has been assigned the id
+ "flowExecutor". This id is significant and is required for the JSF artifacts to detect
+ the executor and its services.
+
+
+
+ Launching the sellitem-flow
+
+ The intro.jsp page shows how the configured web flow sellitem-flow.xml can be launched using
+ a JSF command link component.
<h:form>
<h:commandLink value="Sell Item" action="flowId:sellitem-flow"/>
@@ -1901,30 +1903,26 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
- The JSF version of the sellitem flow definition is simpler because JSF components
- care for data binding and validation.
+ The JSF version of the sellitem flow definition is simpler because JSF components care for data binding and validation.
- In its web flow definition Sellitem-JSF uses actual
- JSP names (instead of the logical view names used
- in Sellitem) to be rendered by JSF.
+ In its web flow definition Sellitem-JSF uses actual JSP names (instead of the logical view names used in Sellitem)
+ to be rendered by JSF. This is consistent with normal JSF-isms.
- The JSP pages in Sellitem-JSF use unified EL to
- access the flowScoped Sale object - e.g. #{sale.price}.
+ The JSP pages in Sellitem-JSF use unified EL to access the converastion scoped Sale object - e.g. #{sale.price}.
- Sellitem-JSF uses JSF tags for UI and Sellitem uses Spring form tags.
+ Sellitem-JSF uses JSF component tags for UI and Sellitem uses Spring form tags.
- There is no need to manually track the flow execution key because it is tracked
- for you in the JSF view root.
+ There is no need to manually track the flow execution key because it is tracked for you in the JSF view root.