portlet and spring mvc docs
This commit is contained in:
@@ -612,7 +612,7 @@
|
||||
name or value
|
||||
</entry>
|
||||
<entry colname="comments">
|
||||
name when in flow element, value when in subflow-state element
|
||||
value when in flow element, name when in subflow-state element
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
|
||||
@@ -5,6 +5,228 @@
|
||||
<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>
|
||||
</chapter>
|
||||
<sect1 id="portlet-config-core">
|
||||
<title>Configuring web.xml & 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[
|
||||
ExternalContextHolder.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[
|
||||
ExternalContextHolder.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>
|
||||
|
||||
@@ -5,6 +5,108 @@
|
||||
<title>Introduction</title>
|
||||
<para>
|
||||
This chapter shows you how to integrate Web Flow into a Spring MVC web application.
|
||||
The <code>booking-mvc</code> sample application is a good reference for Spring MVC with Web Flow.
|
||||
This application is a simplified travel site that allows users to search for and book hotel rooms.
|
||||
</para>
|
||||
</sect1>
|
||||
</chapter>
|
||||
<sect1 id="spring-mvc-config-web.xml">
|
||||
<title>Configuring web.xml</title>
|
||||
<para>
|
||||
The first step to using Spring MVC is to route requests to the <code>DispatcherServlet</code> in the <code>web.xml</code> file.
|
||||
In this example, we map all URLs that begin with <code>/spring/</code> to the servlet.
|
||||
The servlet needs to be configured.
|
||||
An <code>init-param</code> is used in the servlet to pass the <code>contextConfigLocation</code>.
|
||||
This is the location of the Spring configuration for your application.
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<servlet>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>/WEB-INF/web-application-config.xml</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
|
||||
<url-pattern>/spring/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
]]></programlisting>
|
||||
</sect1>
|
||||
<sect1 id="spring-mvc-config-spring">
|
||||
<title>Configuring Spring</title>
|
||||
<sect2 id="spring-mvc-config-spring-url-mapping">
|
||||
<title>URL Mapping</title>
|
||||
<para>
|
||||
Inside the <code>DispatcherServlet</code> request need to be mapped with finer grain.
|
||||
Using a <code>SimpleUrlHandlerMapping</code> request URLs are mapped to controllers and handlers.
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
|
||||
<property name="mappings">
|
||||
<value>
|
||||
/hotels/booking=bookingFlowHandler
|
||||
/hotels/*=hotelsController
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
]]></programlisting>
|
||||
<para>
|
||||
For this example both a standard MVC controller and a Web Flow handler are configured.
|
||||
The controller supports the free navigation aspects of searching and viewing hotels.
|
||||
The flow handler supports the controlled navigation aspect of booking a hotel room.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="spring-mvc-config-spring-flow-adapters">
|
||||
<title>Flow Adapters</title>
|
||||
<para>
|
||||
The recommended way to bridge Spring MVC requests to Web Flow is via a flow adapter.
|
||||
</para>
|
||||
<programlisting language="xml"><![CDATA[
|
||||
<bean id="bookingFlowHandler" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />
|
||||
]]></programlisting>
|
||||
<para>
|
||||
The flow adapter provides hooks into the flow execution that can:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>select the flow to execute (by default the flow id is inferred from the URL)</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>
|
||||
A common pattern to handle a flow outcome is to redirect to a new page instead of rendering a view in the <code>end-state</code>.
|
||||
This allows the URL to be refreshed without throwing an exception.
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
public class BookingFlowHandler extends AbstractFlowHandler {
|
||||
public ModelAndView handleExecutionOutcome(String outcome, AttributeMap output, HttpServletRequest request, HttpServletResponse response) {
|
||||
return new ModelAndView(new RedirectView("/spring/hotels/index", true));
|
||||
}
|
||||
}
|
||||
]]></programlisting>
|
||||
</sect2>
|
||||
<sect2 id="spring-mvc-config-spring-flow-controllers">
|
||||
<title>Flow Controllers</title>
|
||||
<para>
|
||||
Flow controllers provide a direct hook from Spring MVC into Web Flow.
|
||||
The <code>FlowController</code> class is an implementation of an MVC Controller.
|
||||
</para>
|
||||
<para>
|
||||
Web Flow 1.0 used controllers as the only way to hook Web Flow into Spring MVC.
|
||||
In Web Flow 2.0 flow handler adapters are recommended instead of controllers as they provide much richer hooks into the web flow engine.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
@@ -292,7 +292,7 @@ context.addMessage(builder.warn().source("smoking").defaultText("Smoking is bad
|
||||
context.addMessage(builder.info().defaultText("We have processed your reservation - thank you and enjoy your stay").build());
|
||||
</programlisting>
|
||||
</sect2>
|
||||
<sect2 id="plain-text-message">
|
||||
<sect2 id="plain-text-message-intl">
|
||||
<title>Adding internationalized messages</title>
|
||||
<programlisting type="java">
|
||||
MessageContext context = ...
|
||||
|
||||
Reference in New Issue
Block a user