Files
spring-webflow/spring-webflow-reference/src/portlet.xml
2008-04-11 04:01:01 +00:00

229 lines
9.3 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<chapter id="portlet">
<title>Portlet Integration</title>
<sect1 id="portlet-introduction">
<title>Introduction</title>
<para>
This chapter shows you how to use Web Flow in a Portlet environment.
Web Flow has full support for JSR-168 portlets.
The <code>booking-portlet-mvc</code> sample application is a good reference for using Web Flow within a portlet.
This application is a simplified travel site that allows users to search for and book hotel rooms.
</para>
</sect1>
<sect1 id="portlet-config-core">
<title>Configuring web.xml &amp; portlet.xml</title>
<para>
The configuration for a portlet depends on the portlet container used.
The <code>booking-portlet-mvc</code> and <code>booking-portlet-faces</code> sample application are both configured to use <ulink url="http://portals.apache.org/pluto/">Apache Pluto</ulink>, the JSR-168 reference implementation.
</para>
<para>
In general the configuration requires adding a servlet mapping in the <code>web.xml</code> file to dispatch request to the portlet container.
</para>
<programlisting language="xml"><![CDATA[
<servlet>
<servlet-name>swf-booking-mvc</servlet-name>
<servlet-class>org.apache.pluto.core.PortletServlet</servlet-class>
<init-param>
<param-name>portlet-name</param-name>
<param-value>swf-booking-mvc</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>swf-booking-mvc</servlet-name>
<url-pattern>/PlutoInvoker/swf-booking-mvc</url-pattern>
</servlet-mapping>
]]></programlisting>
<para>
The <code>portlet.xml</code> configuration is a standard portlet configuration.
The <code>portlet-class</code> needs to be set along with a pair of <code>init-param</code>s.
Setting the <code>expiration-cache</code> to <code>0</code> is recommended to force Web Flow to always render a fresh view.
</para>
<programlisting language="xml"><![CDATA[
<portlet>
...
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<init-param>
<name>contextConfigLocation</name>
<value>/WEB-INF/web-application-config.xml</value>
</init-param>
<init-param>
<name>viewRendererUrl</name>
<value>/WEB-INF/servlet/view</value>
</init-param>
<expiration-cache>0</expiration-cache>
...
</portlet>
]]></programlisting>
</sect1>
<sect1 id="portlet-config-spring">
<title>Configuring Spring</title>
<sect2 id="portlet-config-spring-handler">
<title>Flow Handlers</title>
<para>
The only supported mechanism for bridging a portlet request to Web Flow is via a <code>FlowHandler</code>.
The <code>PortletFlowController</code> used in Web Flow 1.0 is no longer supported.
</para>
<para>
The flow handler, similar to the servlet flow handler, provides hooks that can:
<itemizedlist>
<listitem>
<para>select the flow to execute</para>
</listitem>
<listitem>
<para>pass input parameters to the flow on initialization</para>
</listitem>
<listitem>
<para>handle the flow execution outcome</para>
</listitem>
<listitem>
<para>handle any exceptions</para>
</listitem>
</itemizedlist>
The <code>AbstractFlowHandler</code> class is an implementation of <code>FlowHandler</code> that provides default implementations for these hooks.
</para>
<para>
In a portlet environment the targeted flow id can not be inferred from the URL and must be defined explicitly in the handler.
</para>
<programlisting language="java"><![CDATA[
public class ViewFlowHandler extends AbstractFlowHandler {
public String getFlowId() {
return "view";
}
}
]]></programlisting>
</sect2>
<sect2 id="portlet-config-spring-mappings">
<title>Adapter Mappings</title>
<para>
Spring Portlet MVC provides a rich set of methods to map portlet requests.
Complete documentation of the available methods is available in the <ulink url="http://static.springframework.org/spring/docs/2.5.x/reference/portlet.html#portlet-handlermapping">Spring Reference Documentation</ulink>.
</para>
<para>
The <code>booking-portlet-mvc</code> sample application uses a <code>PortletModeHandlerMapping</code> to map portlet requests.
The sample application only supports <code>view</code> mode, but support for other portlet modes is available.
Other modes can be added and point to the same flow as <code>view</code> mode, or any other flow.
</para>
<programlisting language="xml"><![CDATA[
<bean id="portletModeHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
<property name="portletModeMap">
<map>
<entry key="view">
<bean class="org.springframework.webflow.samples.booking.ViewFlowHandler" />
</entry>
</map>
</property>
</bean>
]]></programlisting>
</sect2>
<sect2 id="portlet-config-spring-handler-adapter">
<title>Flow Handler Adapter</title>
<para>
A <code>FlowHandlerAdapter</code> converts the handler mappings to the flow handlers.
The flow executor is required as a constructor argument.
</para>
<programlisting language="xml"><![CDATA[
<bean id="flowHandlerAdapter" class="org.springframework.webflow.mvc.portlet.FlowHandlerAdapter">
<constructor-arg ref="flowExecutor" />
</bean>
]]></programlisting>
</sect2>
<sect2 id="portlet-config-spring-redirectonpause">
<title>Redirect on Pause</title>
<para>
In a portlet environemnt, <code>alwaysRedirectOnPause</code> must be set to <code>false</code>.
If not turned off, the initial view will fail to render.
</para>
<programlisting language="xml"><![CDATA[
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<webflow:flow-execution-attributes>
<webflow:alwaysRedirectOnPause value="false"/>
</webflow:flow-execution-attributes>
</webflow:flow-executor>
]]></programlisting>
</sect2>
</sect1>
<sect1 id="portlet-views">
<title>Portlet Views</title>
<para>
In order to facilitate view rendering, a <code>ViewRendererServlet</code> must be added to the <code>web.xml</code> file.
This servlet is not invoked directly, but it used by Web Flow to render views in a portlet environment.
</para>
<programlisting language="xml"><![CDATA[
<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>
]]></programlisting>
</sect1>
<sect1 id="portlet-modes">
<title>Portlet Modes and Window States</title>
<sect2 id="portlet-modes-state">
<title>Window State</title>
<para>
The Portlet API defined three window states: normal, minimized and maximized.
The portlet implementation must decide what to render for each of these window states.
Web Flow exposes the string value of the window state under <code>portletWindowState</code> via the request map on the external context.
</para>
<programlisting language="java"><![CDATA[
requestContext.getExternalContext().getRequestMap().get("portletWindowState");
]]></programlisting>
<programlisting language="el"><![CDATA[
${externalContext.requestMap.portletWindowState}
]]></programlisting>
</sect2>
<sect2 id="portlet-modes-mode">
<title>Portlet Mode</title>
<para>
The Portlet API defined three portlet modes: view, edit and help.
The portlet implementation must decide what to render for each of these modes.
Web Flow exposes the string value of the portlet mode under <code>portletMode</code> via the request map on the external context.
</para>
<programlisting language="java"><![CDATA[
requestContext.getExternalContext().getRequestMap().get("portletMode");
]]></programlisting>
<programlisting language="el"><![CDATA[
${externalContext.requestMap.portletMode}
]]></programlisting>
</sect2>
</sect1>
<sect1 id="portlet-issues">
<title>Issues in a Portlet Environment</title>
<sect2 id="portlet-issues-redirects">
<title>Redirects</title>
<para>
The Portlet API only allows redirects to be requested from an action request.
Because views are rendered on the render request, views and <code>view-state</code>s cannot trigger a redirect.
</para>
</sect2>
<sect2 id="portlet-issues-modes">
<title>Switching Portlet Modes</title>
<para>
The portlet container passes the execution key from the previous flow when switching to a new mode.
Even if the mode is mapped to a different <code>FlowHandler</code> the flow execution will resume the previous execution.
</para>
<para>
One way to start the new flow is to create a URL targeting the mode without the execution key.
</para>
</sect2>
<sect2 id="portlet-issues-jsf">
<title>Portlets and JSF</title>
<para>
Web Flow supports JSF as the view technology for a portlet.
However, a jsf-portlet bridge (JSR-301) must be provided.
At the time of this writing, no feature complete jsf-portlet bridge exists.
Some of the existing bridge implementations may appear to work, however, strange side effect may occur.
</para>
<para>
JSF portlets are considered experimental at this time.
</para>
</sect2>
</sect1>
</chapter>