Support multiple Struts applications

 

Support multiple Struts applications

 

+

Search Tips   |   Advanced Search

 

The Jakarta Struts Framework does not support configuring more than one Struts ActionServlet in the Web deployment descriptor. This limitation occurs because there is only one servlet context per Web application and the commons digester imports the Struts configuration into the servlet context. Struts stores the required information as attributes in the servlet context, and the information is retrieved by using globally defined key names. Struts will suffix these attribute names with the prefix of the Struts modules, so several Struts modules are supported in a single Web application, but multiple Struts applications are not.

The Struts Portlet Framework is used to create Struts applications that are deployed in WebSphere Portal. This section discusses two techniques for creating Web applications that allow packaging more than one Struts-based portlet in a single application. As stated, Jakarta Struts does not support declaring the Struts ActionServlet in the Web deployment descriptor more than once. The Struts Portlet Framework has the same limitation because the servlet context is used when the Struts configuration is digested in the portal as well. However, the Struts Portlet Framework supports two ways that an application can be developed in order to implement multiple Struts-based portlets. The first technique uses a single Struts controller while defining a Struts module for each portlet in the application. The second technique uses a servlet context wrapper that namescopes the attributes stored in the servlet context, so each portlet can have its own namespace in the servlet context.

 

Use Struts modules (IBM portlet container only)

One method of supporting multiple Struts portlets in a single war file is to define a Struts module for each portlet. The welcome file can be specified as a configuration parameter for each concrete portlet. This technique takes advantage of the fact that the Struts Portlet Framework uses the welcome file to set the Struts module. The prefix corresponding to the Struts module for a portlet is stored in the IViewCommand object. The IViewCommand object is retrieved for each portlet and the module prefix is used to select the module, so each portlet in the application will use the Struts module selected during the welcome file processing. Obviously, the portlet can then forward to other modules as well, but initially each portlet can have a unique configuration using the Struts module.

The Struts Portlet Framework controller, WpsStrutsPortlet, is defined as the servlet-class in the Web deployment descriptor. The corresponding abstract portlet is then defined in the portlet deployment descriptor. The application can then define each concrete portlet, and specify a welcome file to use. The configuration for one of the concrete portlets is demonstrated below.

<concrete-portlet-app uid="wp.struts.legacy.examples.MultipleStrutsApp.1">
  <portlet-app-name>Struts Legacy Multiple Modules Application 1</portlet-app-name>
  <concrete-portlet href="#Portlet_1">
    <portlet-name>Struts Legacy Multiple Modules 1</portlet-name>
      <default-locale>en</default-locale>
      <language locale="en">
        <title>Struts Legacy Multiple Modules 1</title>
        <title-short>Struts Legacy Multiple Modules 1</title-short>
        <description>Struts Legacy Multiple Modules 1</description>
        <keywords>WPS, Struts, Legacy</keywords>
      </language>
      <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>
  </concrete-portlet>
</concrete-portlet-app>

The application can configure a separate Struts module that maps to each portlet. This scheme is customizable and will support as many Struts modules as are desirable. However, only one abstract portlet can be defined because there can only be one Struts-based servlet-class. All of the concrete portlets created from the one abstract portlet must share the abstract's portlet configuration. See the SPFLegacyMultipleModules example for more information.

 

Use a namescoped servlet context

Multiple Struts portlets in a single Web application can also be supported by configuring the portlet to use a servlet context wrapper. The (Wps)StrutsPortlet class instantiates the WpsActionServlet object to digest the Struts configuration. The Wp(s)ActionServlet extends the Struts ActionServlet and uses the ActionServlet's init implementation to digest the configuration. The (Wps)StrutsPortlet object will invoke the
init method of the Wp(s)ActionServlet to digest the configuration. Since the (Wps)StrutsPortlet instantiates the Wp(s)ActionServlet and calls the init method, the Struts Portlet Framework has the opportunity to provide a servlet context wrapper. If the application is configured to use the servlet context wrapper, then the Wp(s)ActionServlet will return the servlet context wrapper when the getServletContext method is invoked. The servlet context wrapper defines a namespace unique to the portlet and then stores the attributes in the real servlet context. The concept is similar to how Struts prefixes the attributes in the servlet context for the configuration of each Struts module.

The Wp(s)ActionServlet should be use to obtain the servlet context wrapper when this technique is used. The servlet context obtained from the pageContext, for example, will not be the wrappered servlet context. The Wp(s)ActionServlet can be obtained from the request object using the Globals.ACTION_SERVLET_KEY.

For an IBM portlet container:

The WpsStrutsPortlet class, which is specified as the servlet class in the Web deployment descriptor, can be defined multiple times when the NamescopeServletContext initialization parameter, init-param, is set to true.

<servlet id="wp.struts.legacy.examples.ServletContext.1">
  <servlet-name>StrutsLegacyMultipleServletContexts1</servlet-name>
  <servlet-class>
     com.ibm.wps.portlets.struts.WpsStrutsPortlet   </servlet-class>
  <init-param>
    <param-name>config</param-name>
    <param-value>
       /WEB-INF/portlet1/struts-config.xml     </param-value>
  </init-param>
  <init-param>
    <param-name>struts-servlet-mapping</param-name>
    <param-value>*.do</param-value>
  </init-param>
  <init-param>
    <param-name>NamescopeServletContext</param-name>
    <param-value>true</param-value>
  </init-param>
</servlet>

An abstract portlet for each servlet-class can then be defined in the portlet deployment descriptor.

<portlet id="Portlet_1" 
         href="WEB-INF/web.xml#wp.struts.legacy.examples.ServletContext.1" 
         major-version="1" minor-version="0">
  <portlet-name>
     Struts Legacy Multiple Servlet Contexts 1
  </portlet-name>
    <cache>
      <expires>0</expires>
      <shared>NO</shared>
    </cache>
    <allows>
      <maximized />
      <minimized />
    </allows>
    <supports>
      <markup name="html">
        <view />
        <edit />
      </markup>
    </supports>
  </portlet>

For a standard portlet container:

The StrutsPortlet class, which is specified as the portlet class in the portlet deployment descriptor, can be defined multiple times when the NamescopeServletContext initialization parameter, init-param, is set to true.

<portlet>
   <description xml:lang="en">
      Struts Standard Multiple Servlet Contexts 2
   </description>
   <portlet-name>
      Struts Standard Multiple Servlet Contexts 2
   </portlet-name>
   <display-name xml:lang="en">
      Struts Standard Multiple Servlet Contexts 2
   </display-name>
   <portlet-class>
      com.ibm.portal.struts.portlet.StrutsPortlet    </portlet-class>
   <init-param>
      <name>config</name>
      <value>/WEB-INF/portlet2/struts-config.xml</value>
   </init-param>
   <init-param>
      <name>struts-servlet-mapping</name>
      <value>*.do</value>
   </init-param>
   <init-param>
      <name>NamescopeServletContext</name>
      <value>true</value>
   </init-param>
  ...
</portlet>

Each portlet is independent of the other Struts-based portlets. See the SPFLegacyMultipleServletContexts.war and SPFStandardMultipleServletContexts.war examples for more information.

 

Related information