The MailReader sample is the Apache Struts example shipped with Struts. This sample demonstrates how to write and package a Struts application and many of the features of Apache Struts. There were actually very few changes required to the sample code and JSPs for the application to be packaged for portal. The document will detail the required changes.
This section will discuss the changes to the Apache Struts MailReader example.
The controller for the servlet based Apache Struts is the ActionServlet class. The Struts Portlet Framework provides controller that extends a portlet, instead of a servlet. In the standard container, the controller is specified as the portlet-class in the portlet deployment descriptor.
<portlet> <description xml:lang="en">Struts Standard MailReader</description> <portlet-name>Struts Standard MailReader</portlet-name> <display-name xml:lang="en">Struts Standard MailReader</display-name> <portlet-class>com.ibm.portal.struts.portlet.StrutsPortlet</portlet-class> ... </portlet>
Each portlet is deployed in the application server and therefore requires a servlet mapping. The Struts application also needs a servlet mapping so that the URLs for Struts Actions can be identified. The Struts actions are passed as a request parameter on the portlet URL, so a mapping needs to be specified to identify the Struts action. The Struts servlet mapping is specified as an init parameter.
<init-param> <name>struts-servlet-mapping</name> <value>*.do</value> </init-param>
The Struts Portlet Framework is implemented with a custom request processor. The SPF request processor will split the processing between the two phases of portal. Typically, the request processor is executed in the action phase of portal, and the page can not be rendered. The SPF request processor will save the information from the action phase until the render phase in the IViewCommand object. The SPF request processor is configured in the Struts configuration file, and is required.
<controller processorClass="com.ibm.portal.struts.portlet.WpRequestProcessor"> <!-- The "input" parameter on "action" elements is the name of a local or global "forward" rather than a module-relative path --> <set-property property="inputForward" value="true"/> </controller>
The Struts Portlet Framework requires the URLs that are create to be portlet URLs created using the PortletResponse object. The Struts Action or forward path is then passed to the controller as a request parameter. The URL creation is specific to the Struts Portlet Framework. The Struts Portlet Framework provides the PortletApiUtils impl classes to allow creating the required URLs. Several of the Apache Struts Mail Reader example tags require a change to how the URLs are created so that they can execute in the portal environment.
The LinkSubscriptionTag is modified to use the PortletApiUtils to create the portlet URL. Note, the case where the PortletApiUtils.getUtilsInstance returns null, is the case where the application is running in the servlet environment. The tag can be written to support both the servlet and portlet environment.
// SPF_MODIFICATION PortletApiUtils portletUtils = PortletApiUtils.getUtilsInstance(); if (portletUtils != null) { Object portletURI = portletUtils.createPortletURIWithStrutsURL(request, url.toString()); // don't need to call response.encodeURL, the portletURI.toString takes care of // that. results.append(portletURI.toString() ); } else { results.append(response.encodeURL(url.toString())); } // end SPF_MODIFICATION
The change for LinkUserTag .java is the same change as the one to LinkSubscriptionTag.
// SPF_MODIFICATION PortletApiUtils portletUtils = PortletApiUtils.getUtilsInstance(); if (portletUtils != null) { Object portletURI = portletUtils.createPortletURIWithStrutsURL(request, url.toString() ); // don't need to call response.encodeURL, the portletURI.toString takes care of // that. results.append(portletURI.toString() ); } else { results.append(response.encodeURL(url.toString())); } // end SPF_MODIFICATION
The change required to the CheckLogonTag.java was to support the forward action. Portal does not allow a portlet to forward, the response object has already been committed. The change to the CheckLogonTag is to use the PortletApiUtils.forward, which will include the file, or directly call the RequestProcessor for a Struts Action.
// SPF_MODIFICATION PortletApiUtils portletUtils = PortletApiUtils.getUtilsInstance(); if (portletUtils != null) { HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); portletUtils.forward( config.getPrefix() + page, request ); } else { pageContext.forward( config.getPrefix() + page ); } // end SPF_MODIFICATION
The MailReader sample demonstrates many of the features of Struts. The Apache example was modified to run in the portal environment, this demonstrates some of the migration steps an existing Struts application would need.