Changes to configuration files

Struts Portlet Framework specific init parameters have been added that allows you to customize the Struts application for the portal environment. The portlet and web deployment descriptors require configurations specific to the Struts Portlet Framework. In addition, changes to the Struts configuration file must be made to specify a portal specific request processor as the controller.


Configure the Struts application for the IBM container

Most of the configuration for a Struts application is in the web deployment descriptor file (web.xml). The servlet class that is specified in the web deployment descriptor should be the portlet servlet. The class name is WpsStrutsPortlet. Here is an example definition.

 <servlet id="Servlet_1">
     <servlet-name>MyStrutsApp</servlet-name>
     <servlet-class>com.ibm.wps.portlets.struts.WpsStrutsPortlet
     </servlet-class>
     ...
 </servlet>

When sub-classing WpsStrutsPortlet , you should designate the subclass name for <servlet-name/>. The servlet id should be suffixed with a unique ID to prevent conflicts with other portlets. See Deployment descriptors for more information.

Initialization parameters

Servlet mapping


Configure the Struts application for the standard portlet container

In the standard container the Struts application is configured in the portlet deployment descriptor. The portlet class and init parameters are specified in the portlet deployment description. In the standard container, the only configuration in the web deployment descriptor is the welcome file list and the tag library (taglib) elements. The portlet class that is specified in the portlet deployment descriptor must be the com.ibm.portal.struts.portlet.StrutsPortlet class or subclass.

   <portlet>      
   		<portlet-class>com.ibm.portal.struts.portlet.StrutsPortlet</portlet-class>
   </portlet>

If sub-classing the StrutsPortlet, the subclass class name should be designated as the <portlet-class/>.


Initialization parameters

The following is a list of names of the initialization parameters that can be configured in the web deployment descriptor for Struts portlets (using the <init-param> element):
IncludesSearchPath


ModuleSearchPath


NamescopeFormName


NamescopeServletContext


struts-servlet-mapping


UseGroupsForAccess


UsePortalsLocale


WelcomeFileSearchPath


Set an initial view

The Struts application needs to specify what the initial view is for the application. The typical way that the initial screen is specified is through the welcome file list. The Struts Portlet Framework supports the welcome file list configuration, and has some additional features. The servlet implementation of the welcome file list only supports JSP and HTML pages. The Struts Portlet Framework supports a JSP or HTML welcome file, and also allows a Struts action to be specified as the welcome file. See Example 1 for implementation details.

The alternate method allows Welcome files to be configured on a per portlet basis as a configuration parameter in the portlet deployment descriptor portlet.xml. The default search will look for the initial view file per portlet mode. The other feature in the Struts Portlet Framework is the support for modules. A unique welcome file should be configured for each module by specifying the application prefix. For example, to support the view mode for the markup WML, a welcome file wml/view can be specified. See Example 2 for implementation details.

Figure 1. Example 1: Welcome file list that is specified in the file web.xml

<welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>help/index.jsp</welcome-file>
  <welcome-file>wml/view/index.jsp</welcome-file>
</welcome-file-list>

Figure 2. Example 2: Welcome file list that is specified on a per portlet basis (standard portlets)

      <portlet-preferences>
         <preference>
            <name>viewMode.page</name>
            <value>portlet1/welcome.jsp</value>
         </preference>
         <preference>
            <name>editMode.page</name>
            <value>html/edit/index.jsp</value>
         </preference>
      </portlet-preferences>

Figure 3. Example 3: Welcome file list that is specified on a per portlet basis (IBM)

           <config-param>
               <param-name>viewMode.page</param-name>
               <param-value>portlet1/welcome.jsp</param-value>
            </config-param>
            <config-param>
               <param-name>editMode.page</param-name>
               <param-value>portlet1/edit.jsp</param-value>
            </config-param>


Use modes

The Struts Portlet Framework is set up to use the mode and markup to find the Struts configuration. However, if you do not want to use a Struts application in one of the modes, the Struts portlet (Wps)StrutsPortlet should be subclassed. The appropriate service() method should be overridden to implement the wanted behavior. For example, if the developer wants a help mode that does not use a Struts application, then the doHelp() method should be implemented in a subclass.

Portlet modes can be supported with the Struts Portlet framework. The Struts Portlet Framework stores the IViewCommand objects on a per mode basis. That means that an application that supports view and edit mode will have an IViewCommand object for view and edit mode. The welcome file list is typically used for the initial page when entering a mode.

The SPFLegacyMultipleModules.war example for the IBM container and the SPFStandardMultipleModules.war example for the standard portlet container demonstrate support for edit mode. The Module 1 portlet implements an edit mode wizard that steps through three screens. The example also demonstrates how to use a StrutsActionForward so that the IViewCommand object for the last page of the wizard can be marked for removal on a mode change. This allows the IViewCommand object for edit mode to be deleted when the user switches from edit mode back to view. The anticipated use is that the user is entering data in edit mode and the configuration data is submitted to be stored. The last page displays that the data has been successfully stored. The user then leaves edit mode using the skin. If the user goes back into edit mode, they do not want to see the message that the data was successfully stored. Since the command was deleted, the welcome file list entry can be used to start the wizard again. This feature also reduces the number of attributes stored in session.

      <action path="/nextEditPage2" 
              type="com.ibm.wps.struts.example.multipleapps.actions.ForwardAction">
              <forward className="com.ibm.wps.struts.action.StrutsActionForward"
                       name="success" 
                       path="/edit3.jsp">
                      <set-property property="removeOnModeChange"
                                    value="true"/>
               </forward>
      </action>


The Struts example application demonstrates support for help mode. A Struts configuration has been added to the web deployment descriptor, web.xml, to demonstrate help mode. This mode is entered when the user clicks the help button for the Struts example portlet. The following code fragment from the web deployment descriptor demonstrates how to configure the struts-configuration to support help mode.

<init-param>
 <param-name>config/html/help</param-name>
 <param-value>/WEB-INF/html/help/struts-config.xml</param-value>
</init-param>

The search path set in the web deployment descriptor includes mode, which enables a separate Struts configuration for a mode.

<init-param>
 <param-name>ModuleSearchPath</param-name>
 <param-value>markupName, porletMode</param-value>
</init-param>

The welcome file list defines the welcome file for the help mode, as follows:

<welcome-file-list>
 <welcome-file>index.jsp</welcome-file>
 <welcome-file>html/help/index.jsp</welcome-file>
 <welcome-file>wml/view/index.jsp</welcome-file>
</welcome-file-list>


Support for devices

The Struts Portlet Framework's support of devices was designed to be flexible. The way the configuration and JSP files are placed in the directory structure should be tolerant of the devices that need to be supported. Some applications may just support HTML browsers and only need a single Struts configuration file. Other applications may support multiple markups and locales but do not need to know specifics about the device itself, while other implementations may need unique implementations for each of the supported devices. This support requires extension mapping. The prefix mapping only supports only a single configuration file.

WebSphere Portal is designed to allow portlets to access information about the client device, such as locale and markup language supported, using the Client interface. The Struts support for modes and markups has been implemented by allowing a configuration parameter to specify the fields in the client object that are interesting. The Client object is treated like a bean, where the field value corresponds to a get method in the Client object. This allows developers to specify the fields in the Client object that are necessary to their device support. The standard portlet container does not have a Client object but the following fields are supported:

There are two paths that can be specified for supporting modes and device types (clients). The first path is the search path, and that path is used to specify the module to use. The search path locates the appropriate Struts configuration to use and is the prefix used as the base directory for the necessary JSPs. The default search path is markupName, portletMode. This will search for a configuration based on the current markup and the portlet mode.

<init-param>
  <param-name>ModuleSearchPath</param-name>
  <param-value>markupName, portletMode</param-value>
</init-param>

For example, if a desktop browser is used and the user is in view mode, then the search path would be:

And if the Client object specified "wml" as the markupName then the search path would be:

The search path is checked against all of the prefixes for the ModuleConfig objects for a match. The modules are configured in the web deployment descriptor, web.xml, by specifying a prefix for a Struts configuration.

For example, a module for the WML markup in view mode would be configured by adding a configuration to the web deployment descriptor like:

<init-param>
   <param-name>config/wml/view</param-name>
   <param-value>/WEB-INF/wml/view/struts-config.xml</param-value>
</init-param>

If the wml/view module is selected, the corresponding JSPs are searched for under the wml/view directory of the Struts application WAR file.

This is a good start for separating the files for different markups and modes, but this granularity is probably not enough to deal with all available devices, or even locales. You can modify this search path to have a finer granularity. For example, you could create a unique module for every phone that they support.

The search path of markupName, portletMode, locale, manufacturer, model, and version could be used. This offers a very fine-grained deployment of the JSPs. The problem with this approach is that the majority of the JSPs would probably be the same for each of the devices. There are probably a few that need to be modified for each device, but this approach does not allow sharing.

This is why two paths are offered, search and include. The search path is used to find the module. This would be for applications that can use a common configuration, share actions and some of the JSPs. The include path can then be used to look for specific implementations of the JSP and if not found, fall back to a common file.

Take the following include path for including JSPs that are dependent on the device.

<init-param>
   <param-name>IncludesSearchPath</param-name>
   <param-value>manufacturer, model, version</param-value>
</init-param>

This would search for the file relative to the module and then take the requested fields into account. So if the search path found the wml/view module and the file index.jsp is requested, then the above search path for an ACME T400 would be as follows:

Note that version did not show up in the search. That is because the default client configuration for the T400 did not have one defined. If one was configured at a later time, then it would be used.

Portal aggregation is flexible in how the differences between devices are supported. The common features are supported through the search path; all WML devices in view mode in a locale. The subtitle differences between devices would be supported through the file search of the include path. The common versions of the JSPs would be at a root level, and specific files would be at lower levels.

The Struts example ships with several tags, two of which required a minor change to support modules. The LinkSubscriptionTag and LinkUserTag tags had to be modified so that the current ModuleConfig's prefix had to be added to the computed URL.


Internationalization support

The Struts Portlet Framework supports i18n through the use of resource bundles. Each Struts application can specify a message resource. The Java resource bundle implementation determines the resource bundle to use based on the locale and variant. The Struts application typically uses the message tag to include translated text from the application-supplied resource bundle.

<init-param>
  <param-name>IncludesSearchPath</param-name>
  <param-value>locale</param-value>
</init-param>

The Struts framework was designed to give the application control over locale by using a locale object that is set in session with a known key. The Struts RequestProcessor sets the locale object for each user during the processLocale() method. The processLocale() method sets the locale object using the key Globals.LOCALE_KEY if the feature is enabled through the Struts configuration file and the attribute has not already been set in session.

A setting on the controller element that is available in the Struts configuration file controls the locale support in Struts. The support can be turned off, which will stop the locale processing in the Request Processor processLocale() method.

WebSphere Portal supports dynamic changes to the locale. Portlets should use the locale object that is obtained through the PortletRequest object for the locale setting. The Struts Portlet Framework sets the locale object in the session using the key Globals.LOCALE_KEY during the actionPerformed() and service() methods. The support is implemented by calling the (Wps)StrutsPortlet processLocale() method, which sets the locale object if one is not found or the locale is different than the one already in session. This assures that a portlet written using the Struts Portlet Framework uses the correct locale.

Locale support can also be customized. The (Wps)StrutsPortlet processLocale() method can be overridden for a customized implementation. The invocation of (Wps)StrutsPortlet processLocale() can also be stopped by adding the following init-parameter to the web deployment descriptor for the application.

<init-param>
  <param-name>UsePortalsLocale</param-name>
  <param-value>false</param-value>
</init-param>         


However, in most cases the portlet should use the default implementation.


Use the IBM container

WebSphere Portal also provides an implementation to find globalized JSPs using the include() method on PortletContext. PortletContext inserts the locale into the path to locate the locale-specific JSP. For more information, see Generating markup for multiple devices, markups, and languages.

The Struts Application can be deployed to use the portal server's aggregation method to find globalized JSPs, instead of a resource bundles for each locale. The Struts Portlet Framework uses the PortletContext.include() on the legacy container to include JSP pages, so both methods of globalization are supported.

PortletContext.include() searches for locale-specific files by inserting the markup and locale name in the path. This behavior can be configured through an initialization parameter in the web deployment descriptor. An include search path can be specified that controls how the includes are located. For example, the default implementation would be markup, locale but can be changed to just locale if required. The mode and markup support may have been already configured to include markup, so this configuration allows the markup to not be needed a second time.


WML support

Because WebSphere Portal supports pervasive devices, such as WAP phones, the example has been configured to support a generic WML device. Adding a Struts configuration for WML devices supports the view mode for a WML device. The following code fragment demonstrates how to set up the struts-configuration for the view mode for WML markup.

<init-param>
 <param-name>config/wml/view</param-name>
 <param-value>/WEB-INF/wml/view/struts-config.xml</param-value>
</init-param>

The search path that is set up in the web deployment descriptor, takes markup, mode, and locale into account. When a WAP device connects to a portal server, the markup will be WML, and the mode will be view. This example does not use the locale that is requested.

The welcome file list also defines the welcome file for the wml/view mode.

<welcome-file-list>
 <welcome-file>index.jsp</welcome-file>
 <welcome-file>html/help/index.jsp</welcome-file>
 <welcome-file>wml/view/index.jsp</welcome-file>
</welcome-file-list>

For more information about WML support in the Struts Portlet Framework, see Changes to Struts JSPs.


Logging

The Struts Portlet Framework uses the Commons-Logging interface for a logging facility. The Struts Portlet Framework has supplied an implementation of the Commons-Logging Log interface that can be used to map the trace messages to the logging facility used by the portal server. This file is normally found in the $PORTAL_HOME/log directory. Setting properties in the WP_PROFILE/PortalServer/config/config/log.properties file enables trace logging. The trace string for tracing a Struts portlet application can be configured in log.properties. The trace string can be modified to add or remove classes. The entire trace string must be on one line in log.properties.

The logging in WebSphere Portal typically creates a logging object per class and the trace messages display the log class that the message is from. This is very convenient to determine where a trace message originated from and also allows only enabling the tracing on certain classes.

The typical trace string configured in the log.properties file for tracing a Struts application would be as shown below (all on one line). This can be modified to add or remove classes.
IBM container:


JSR compliant container:


Customize logging


Struts Portlet Framework version 5.0.3 or later Log Factory's class name


Overriding the default logging implementation class


Logging conflict between new and old versions of Struts portlets


Commons Logging jar


Changes to the Struts configuration file

The Struts configuration used by Struts portlets references the 1.1 version of the DTD.

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

In order to have the Struts Portlet Framework operate properly, the RequestProcessor must be configured. The RequestProcessor is responsible for the main functionality of processing a request. The default RequestProcessor can be overridden in the struts-config.xml via the controller element. In the struts-config.xml, the following portal server RequestProcessor must be specified:
Standard portlet container:


IBM portlet container:

Of course, you may also have had the need to extend the Struts RequestProcessor in order to extend the functionality of Struts. If you simply place the path to RequestProcessor in the controller element in the struts-config file, application will not work properly in the portlet environment. Instead, what you should do is have RequestProcessor class extend the WpsRequestProcessor rather than the normal Struts RequestProcessor.

The following are the methods overridden in WpsRequestProcessor:

If you override any of the methods listed above, you should make sure to invoke the super class version of the method from within method.

There are existing Struts Extensions which require you to use their RequestProcessor. Clearly, you cannot use their RequestProcessor and the WpsRequestProcessor at the same time. Instead, you would need to get the source to that RequestProcessor and following the approach just described.


Tiles support

Struts integrates the Tiles package for creating views. A Tiles sample is included with the Struts Portlet Framework that demonstrates how to configure Tiles in the Struts Portlet Framework. Tiles requires a specific Request Processor that is configured through a plug-in. The following is from the Struts configuration to show how to configure Tiles for a Struts application that is deployed in WebSphere Portal.
Standard portlet container:


IBM portlet container:


Parent

Struts Portlet Framework

 


+

Search Tips   |   Advanced Search