reference documentation updates for jsf

This commit is contained in:
Keith Donald
2007-04-10 16:04:12 +00:00
parent db4a657900
commit 6bbf579da1
2 changed files with 207 additions and 102 deletions

View File

@@ -521,74 +521,28 @@
<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. 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.
</para>
<para>
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.
</para>
<sect2 id="executor-jsf-simple">
<title>A typical faces-config.xml file</title>
<programlisting>
&lt;faces-config&gt;
&lt;application&gt;
&lt;navigation-handler&gt;
org.springframework.webflow.executor.jsf.FlowNavigationHandler
&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;
org.springframework.webflow.executor.jsf.FlowExecutionVariableResolver
&lt;/variable-resolver&gt;
&lt;property-resolver&gt;
org.springframework.webflow.executor.jsf.FlowExecutionPropertyResolver
&lt;/property-resolver&gt;
&lt;/application&gt;
&lt;lifecycle&gt;
&lt;phase-listener&gt;org.springframework.webflow.executor.jsf.FlowPhaseListener&lt;/phase-listener&gt;
&lt;/lifecycle&gt;
&lt;/faces-config&gt;
</programlisting>
</sect2>
<sect2 id="executor-jsf-launch-get">
<title>Launching a flow execution - command link</title>
<programlisting>
&lt;h:commandLink value="Go" action="flowId:myflow"/&gt;
</programlisting>
</sect2>
<sect2 id="executor-jsf-resume-form">
<title>Resuming a flow execution - form bound to flow execution variables</title>
<programlisting>
&lt;h:form id="form"&gt;
...
&lt;h:inputText id="propertyName" value="#{flowExecution.flashScope.aFlashScopeAttribute}"/&gt;
&lt;h:inputText id="propertyName" value="#{flowExecution.flowScope.aFlowScopeAttribute}"/&gt;
&lt;h:inputText id="propertyName" value="#{flowExecution.conversationScope.aConversationScopeAttribute}"/&gt;
&lt;h:inputText id="propertyName" value="#{flowExecution.anAttributeToSearchForAcrossAllScopes}"/&gt;
...
&lt;input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"&gt;
&lt;h:commandButton type="submit" value="Next" action="submit"/&gt;
&lt;/h:form&gt;
</programlisting>
</sect2>
<sect2 id="executor-jsf-simple-pre-102">
<title>A pre Spring Web Flow 1.0.2 faces-config.xml file</title>
<title>A minimal faces-config.xml file</title>
<para>
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
<literal>faces-config.xml</literal> file:
</para>
<programlisting>
&lt;faces-config&gt;
&lt;application&gt;
&lt;navigation-handler&gt;
org.springframework.webflow.executor.jsf.FlowNavigationHandler
&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;
org.springframework.webflow.executor.jsf.FlowVariableResolver
&lt;/variable-resolver&gt;
&lt;property-resolver&gt;
org.springframework.webflow.executor.jsf.FlowPropertyResolver
&lt;/property-resolver&gt;
&lt;navigation-handler&gt;org.springframework.webflow.executor.jsf.FlowNavigationHandler&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver&lt;/variable-resolver&gt;
&lt;/application&gt;
&lt;lifecycle&gt;
@@ -596,10 +550,158 @@
&lt;/lifecycle&gt;
&lt;/faces-config&gt;
</programlisting>
<para>
The <classname>FlowPhaseListener</classname> 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.
</para>
<para>
The <classname>FlowNavigationHandler</classname> 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.
</para>
<para>
The <classname>DelegatingFlowVariableResolver</classname> 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.
</para>
</sect2>
<sect2 id="executor-jsf-launch-commandlink">
<title>Launching a flow execution - JSF command link component</title>
<para>
Flows can be launched by firing JSF action outcomes that adhere to a special format:
</para>
<programlisting>
&lt;h:commandLink value="Go" action="flowId:myflow"/&gt;
</programlisting>
<para>
The command link above says <emphasis>launch 'myflow' when clicked</emphasis>.
By default, an action outcome prefixed with <literal>flowId:</literal> will treated as a flow definition identifier.
The FlowNavigationHandler will launch a new execution of that flow definition.
</para>
<para>
The flow id prefix respected by the FlowNavigationHandler is configurable. See the API documentation for
more information.
</para>
</sect2>
<sect2 id="executor-jsf-launch-normal-anchor">
<title>Launching a flow execution - normal HTML anchor</title>
<para>
Flows can also be launched simply by accessing flow definition URLs directly using a bookmark or normal HTML link:
</para>
<programlisting>
&lt;a href="app.faces?flowId=myflow"&gt;Go&lt;/a&gt;
</programlisting>
<para>
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.
</para>
</sect2>
<sect2 id="executor-jsf-sampleflow">
<title>Sample flow in a JSF environment</title>
<para>
Flow definitions in a JSF environment are just plain Spring Web Flow definitions:
</para>
<programlisting>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
&lt;var name="bean" class="example.ManagedBeanImpl" scope="conversation" /&gt;
&lt;start-state idref="displayView" /&gt;
&lt;view-state id="displayView" view="/myview.jsp"&gt;
&lt;transition on="submit" to="displayNextView"/&gt;
&lt;/view-state>
&lt;view-state id="displayNextView" view="/nextview.jsp" /&gt;
&lt;/flow&gt;
</programlisting>
<para>
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.
</para>
<para>
How Spring Web Flow view names are mapped to JSF view ids is configurable. See the
<classname>FlowPhaseListener</classname> API documentation for more information.
</para>
</sect2>
<sect2 id="executor-jsf-resume-form">
<title>Resuming a flow execution - form bound to flow execution variables</title>
<para>
Views participating in flows are just plain JSF views. They may also incorporate other
JSF view technologies such as Facelets and Ajax4JSF.
</para>
<programlisting>
&lt;f:view&gt;
&lt;h:form id="form"&gt;
...
&lt;h:inputText id="propertyName" value="#{someBean.someProperty}"/&gt;
...
&lt;h:commandButton type="submit" value="Next" action="submit"/&gt;
&lt;/h:form&gt;
&lt;/f:view&gt;
</programlisting>
<para>
As shown above, there is nothing Spring Web Flow specific here. The flow execution
key is automatically tracked by a special UI component in the view root, so there is no need to
track it manually. Action outcomes are automatically mapped to Spring Web Flow event identifiers
signaled against the current state.
</para>
</sect2>
<sect2 id="executor-jsf-sample">
<title>Spring Web Flow JSF Integration Samples</title>
<para>
See the <link linkend="sellitem-JSF-sample">sellitem-jsf</link> sample that illustrates Spring Web Flow operating in
a JSF environment.
</para>
</sect2>
<sect2 id="executor-jsf-simple-pre-102">
<title>A pre Spring Web Flow 1.0.2 faces-config.xml file</title>
<note>
<para>This section applies to those using Spring Web Flow's JSF integration before release 1.0.2.</para>
</note>
<para>
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:
</para>
<programlisting>
&lt;faces-config&gt;
&lt;application&gt;
&lt;navigation-handler&gt;org.springframework.webflow.executor.jsf.FlowNavigationHandler&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;org.springframework.webflow.executor.jsf.FlowVariableResolver&lt;/variable-resolver&gt;
&lt;property-resolver&gt;org.springframework.webflow.executor.jsf.FlowPropertyResolver&lt;/property-resolver&gt;
&lt;/application&gt;
&lt;lifecycle&gt;
&lt;phase-listener&gt;org.springframework.webflow.executor.jsf.FlowPhaseListener&lt;/phase-listener&gt;
&lt;/lifecycle&gt;
&lt;/faces-config&gt;
</programlisting>
<note>
<para>
With 1.0.2 <classname>DelegatingFlowVariableResolver</classname> 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.
</para>
</note>
</sect2>
<sect2 id="executor-jsf-resume-form-pre-102">
<title>Resuming a flow execution - pre 1.0.2 form bound to flow scope variables</title>
<title>Resuming a flow execution - pre Spring Web Flow 1.0.2</title>
<para>
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 <emphasis>just plain JSF</emphasis>.
</para>
<programlisting>
&lt;f:view&gt;
&lt;h:form id="form"&gt;
...
&lt;h:inputText id="propertyName" value="#{flowScope.aFlowScopeAttribute}"/&gt;
@@ -607,7 +709,12 @@
&lt;input type="hidden" name="_flowExecutionKey" value="${flowExecutionKey}"&gt;
&lt;h:commandButton type="submit" value="Next" action="submit"/&gt;
&lt;/h:form&gt;
&lt;/f:view&gt;
</programlisting>
<para>
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.
</para>
</sect2>
</sect1>
</chapter>

View File

@@ -1766,8 +1766,8 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
<title>Overview</title>
<para>
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.
</para>
<note>
@@ -1785,7 +1785,7 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
<title>Web.xml</title>
<para>
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":
<programlisting>
&lt;!-- Faces Servlet --&gt;
&lt;servlet&gt;
@@ -1796,13 +1796,13 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;
&lt;url-pattern&gt;*.jsf&lt;/url-pattern&gt;
&lt;url-pattern&gt;*.faces&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</programlisting>
</para>
<para>
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:
<programlisting>
&lt;context-param&gt;
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
@@ -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.
</para>
</sect2>
<sect2>
<title>JSF Setup in faces-config.xml</title>
<title>Web Flow JSF Setup in faces-config.xml</title>
<para>
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:
<programlisting>
&lt;application&gt;
&lt;!-- Navigation handler proxy for a Spring-managed bean that is the Web Flow Navigation Handler --&gt;
&lt;navigation-handler&gt;
org.springframework.webflow.executor.jsf.FlowNavigationHandler
&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;
org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver
&lt;/variable-resolver&gt;
&lt;navigation-handler&gt;org.springframework.webflow.executor.jsf.FlowNavigationHandler&lt;/navigation-handler&gt;
&lt;variable-resolver&gt;org.springframework.webflow.executor.jsf.DelegatingFlowVariableResolver&lt;/variable-resolver&gt;
&lt;/application&gt;
&lt;lifecycle&gt;
&lt;phase-listener&gt;org.springframework.webflow.executor.jsf.FlowPhaseListener&lt;/phase-listener&gt;
&lt;/lifecycle&gt;
@@ -1866,27 +1860,35 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
</para>
</sect2>
<sect2>
<title>Web Flow Definitions</title>
<title>Web Flow System Setup in webflow-config.xml</title>
<para>
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.
</para>
<para>
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:
<programlisting>
&lt;!-- Launches new flow executions and resumes existing executions --&gt;
&lt;flow:executor id="flowExecutor" registry-ref="flowRegistry" /&gt;
&lt;!-- Creates the registry of flow definitions for this application --&gt;
&lt;flow:registry id="flowDefinitionLocator"&gt;
&lt;flow:registry id="flowRegistry"&gt;
&lt;flow:location path="/WEB-INF/flows/sellitem-flow.xml" /&gt;
&lt;/flow:registry&gt;
</programlisting>
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.
</para>
</sect2>
<sect2>
<title>Launching the sellitem-flow</title>
<para>
The intro.jsp page shows how the configured web flow sellitem-flow.xml can be launched using
a JSF command link component.
<programlisting>
&lt;h:form&gt;
&lt;h:commandLink value="Sell Item" action="flowId:sellitem-flow"/&gt;
@@ -1901,30 +1903,26 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
<orderedlist>
<listitem>
<para>
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.
</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
<listitem>
<para>
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}.
</para>
</listitem>
<listitem>
<para>Sellitem-JSF uses JSF tags for UI and Sellitem uses Spring form tags.</para>
<para>Sellitem-JSF uses JSF component tags for UI and Sellitem uses Spring form tags.</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
</orderedlist>