diff --git a/spring-webflow/docs/reference/src/practical.xml b/spring-webflow/docs/reference/src/practical.xml
index d5f521e6..3df53df3 100644
--- a/spring-webflow/docs/reference/src/practical.xml
+++ b/spring-webflow/docs/reference/src/practical.xml
@@ -59,7 +59,10 @@
- Phonebook-Portlet - the phonebook sample in a Portlet environment (notice how the flow definitions do not change).
+
+ Phonebook-Portlet - the
+ phonebook sample in a Portlet environment (notice how the flow definitions do not change).
+
@@ -2014,4 +2017,230 @@ public void registerCustomEditors(PropertyEditorRegistry registry) {
+
+ Phonebook-Portlet Example
+
+ Overview
+
+ The Phonebook-Portlet demonstrates how to run the
+ Phonebook
+ sample as a JSR-168 portlet. The functionality for Phonebook and Phonebook-Portlet
+ including web flow definitions, JSP pages, and Java classes is the same and
+ already well documented.
+ The focus in Phonebook-Portlet is specifically on how to configure
+ and run Phonebook in a Portal container.
+
+
+
+ JSR-168 defines portlets but not how portlets integrate into a
+ portal container. This process is left open to portal vendors who
+ have their own individual mechanisms.
+ The Phonebook-Portlet sample is configured to run with
+ Apache Pluto -
+ a reference implementation of the Java Portlet Specification.
+ However, its dependence on Pluto is limited to configuration in web.xml.
+ Hence it should be easy to adapt for use
+ in other Portal/Portlet implementations after learning the
+ deployment steps specific for that implementation.
+
+
+
+
+ Portal/Portlet Related Software Used in the Sample
+
+ This section provides a very brief introduction to the portal related
+ supporting software used in the sample - namely Apache Pluto
+ and the Portlet MVC framework. If this is not new for you
+ feel free to skip to the next section.
+
+
+ Apache Pluto
+
+ For those familiar with servlet applications the process
+ of deploying and running a portlet application can be
+ confusing and requires some explanation.
+ Typically an application with JSR-168 portlets runs in
+ one webapp while a portal/portlet container runs
+ in a separate webapp making cross-context calls to
+ portlets. How exactly this is configured
+ depends on each portal vendor.
+
+
+ Pluto is an open-source reference implementation of the
+ Java Portlet specification. The following general steps
+ are required to run portlets with it. First the
+ the portlet application's web.xml is "injected" with
+ configuration required for Pluto. Secondly Pluto's
+ Portal web application, usually set to run at
+ http://localhost:8080/pluto/portal
+ is used to add or remove portlets to one or more
+ portal container pages.
+
+
+ The web.xml for the Phonebook-Portlet sample has
+ already been "injected" with the configuration required
+ for Pluto 1.1.0. Although this enables it for use with Pluto
+ you must still use the
+ admin pages of Pluto's Portal web application to add
+ the Phonebook-Portlet to a test portal page. For more
+ information on how to do this please follow instructions from
+ Apache Pluto.
+
+
+
+ Portlet MVC Framework
+
+ The Portlet MVC framework represents Spring's support for JSR-168.
+ It has many parallels with the Spring MVC framework such
+ as the DispatcherPortlet, the Controller interface,
+ handler mappings, view resolvers, and exception handlers.
+ The main differences between Portlet MVC and Spring MVC
+ have to do with the lifecycles of a portlet and its
+ distinct phases as defined in the Porlet Specification:
+ the action and the render phases.
+ For more information see
+
+ Chapter 16 (Portlet MVC Framework) from the Spring reference
+ documentation.
+
+
+
+
+ Portlet.xml Configuration
+
+ Portlet.xml is a standard deployment descriptor where
+ portlet resources are defined. The Phonebook-Portlet
+ is based the Portlet MVC DispatcherPorlet:
+
+<portlet-class>
+ org.springframework.web.portlet.DispatcherPortlet
+</portlet-class>
+
+ The DispatcherPortlet is Spring's implementation of the Portlet interface
+ dispatching requests for a portlet to registered Portlet MVC handlers.
+ The phonebook portlet is configured with the following Spring
+ contexts containing Portlet MVC handler, controller and
+ view resolver beans:
+
+<init-param>
+ <name>contextConfigLocation</name>
+ <value>
+ /WEB-INF/phonebook-portlet-config.xml /WEB-INF/phonebook-webflow-config.xml
+ </value>
+</init-param>
+
+ The above configuration defines phonebook as a portlet resource. In order
+ to use it in a portal/portlet container
+ additional web.xml configuration is required.
+
+
+
+ Web.xml Configuration
+
+ The Java Portlet Specification is defined as a layer over existing Servlet
+ infrastructure. Therefore some sort of a servlet is required to accept servlet
+ requests and expose portlet resources. Portal vendors
+ provide such servlets and specific configuration varies by vendor.
+ The Phonebook-Portlet has the following Apache Pluto servlet definition
+ and servlet mapping:
+
+<!-- Generated Portlet Wrapper Servlet for Apache Pluto deployment -->
+<servlet>
+ <servlet-name>phonebook</servlet-name>
+ <servlet-class>org.apache.pluto.core.PortletServlet</servlet-class>
+ <init-param>
+ <param-name>portlet-name</param-name>
+ <param-value>phonebook</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+</servlet>
+<servlet-mapping>
+ <servlet-name>phonebook</servlet-name>
+ <url-pattern>/PlutoInvoker/phonebook</url-pattern>
+</servlet-mapping>
+
+
+
+
+ The above configuration was auto generated using ant tasks from
+ Apache Pluto 1.1.0. This configuration is included in web.xml
+ for convenience and also as an example.
+ For the most up-to-date information on required configuration please
+ check Pluto's documentation.
+
+
+
+ The web.xml configuration also contains the following servlet definition:
+
+<servlet>
+ <servlet-name>viewRendererServlet</servlet-name>
+ <servlet-class>
+ org.springframework.web.servlet.ViewRendererServlet
+ </servlet-class>
+</servlet>
+<servlet-mapping>
+ <servlet-name>viewRendererServlet</servlet-name>
+ <url-pattern>/WEB-INF/servlet/view</url-pattern>
+</servlet-mapping>
+
+
+
+ The main purpose of this servlet is to allow reuse of Spring MVC's flexible
+ view resolution and rendering capabilities in a Portlet application.
+ The DispatcherPortlet converts a PortletRequest/PortletResponse to an
+ HttpServletRequest/HttpServletResponse and then performs an include of
+ this servlet.
+
+
+
+ Portlet MVC Configuration
+
+ The phonebook-portlet-config.xml is very similar to the Spring MVC
+ equivalent phonebook-servlet.xml from the Phonebook sample. The main
+ difference is in the use of a PortletModeHandlerMapping:
+
+<bean id="portletModeControllerMapping"
+ class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
+ <property name="portletModeMap">
+ <map>
+ <entry key="view" value-ref="flowController"/>
+ </map>
+ </property>
+</bean>
+
+ and a PortletFlowController:
+
+<bean id="flowController" class="org.springframework.webflow.executor.mvc.PortletFlowController">
+ <property name="flowExecutor" ref="flowExecutor"/>
+ <property name="defaultFlowId" value="search-flow"/>
+</bean>
+
+ A PortletModeHandlerMapping allows mapping specific to each
+ portlet mode. The VIEW mode in this case is mapped to the
+ flowController bean, which delegates the request to Web Flow's
+ executor for launching or resuming a flow from a flow definition.
+ For more information on Phonebook flow definitions please
+ refer to the
+ Phonebook
+ sample documentation.
+
+
+ One last thing to observe is the following configuration in
+ /WEB-INF/phonebook-webflow-config.xml:
+
+<!-- Launches new flow executions and resumes existing executions. -->
+<flow:executor id="flowExecutor" registry-ref="flowRegistry">
+ <flow:execution-attributes>
+ <!-- execution redirects don't apply in a Portlet environment -->
+ <flow:alwaysRedirectOnPause value="false"/>
+ </flow:execution-attributes>
+</flow:executor>
+
+ As the comment indicates the default behavior of redirect after submit
+ must be turned off in a portlet environment where there is no HTTP redirect.
+ For more information on the alwaysRedirectOnPause refer to the following
+ article.
+
+
+