Rapidly implementing portal look-and-feel using Struts Tiles and the Portlet Framework in WebSphere Application Server V6.1

This article tells you how to create portal pages using the JSR168 portlet container framework and aggregation tags in IBM® WebSphere® Application Server Version 6.1 (hereafter called Application Server) integrated with Struts Tiles. It is intended for Web application developers who want to quickly integrate existing or separately-developed JSR 168 portlets into Web pages to achieve a portal look-and-feel. You should have a good understanding of Java programming, portlets, the Struts Title framework and Application Server. See Resources for references which can help you learn more about these topics.

Share:

Shunguo Yan (shunguoy@us.ibm.com), Advisory Software Engineer, IBM, Intel, Microsoft,HP

Shunguo Yan is an Advisory Software Engineer in the Application and Integration Middleware division of IBM software group in Austin. He currently works on WebSphere Telecom Web Service Server and the IP Multimedia Subsystem (IMS) Solution. His major responsibility is to design and develop integrated solutions for various industries using J2EE, XML, Web services, and IBM software products.



07 March 2007

Also available in Japanese

Introduction

Beginning with Version 6.1, WebSphere Application Server provides an embedded JSR168 portlet container. You can now deploy portlets, which could previously only be deployed to a portal server (such as IBM WebSphere Portal, hereafter called WebSphere Portal), to Application Server V6.1.

This capability provides several major advantages:

  1. You can write portlets as reusable components, use them first in Application Server, and later use them in a JSR 168-compatible portal server (such as WebSphere Portal) to use more advanced features in the portal server.
  2. You can integrate standard portlets that are written by others, from open source or commercial portlet catalogs (such as the WebSphere Portal catalog), in Application Server.
  3. You can deploy a portlet along side a servlet to meet various business needs. For example, you might want to use portlets to provide an aggregated view of various data, and use servlets to handle complex a user interface with lots of page flows.
  4. Your application is more portable to pervasive devices with various screen sizes because portlets, which each occupy a small rectangle region on a page, can be easily rendered on a pervasive device. For example, your application might specify a single portlet to occupy the entire screen in a cellular phone; two portlets in a pocket PC side-by-side; and, multiple portlets to be rendered into a Web browser.

However, Application Server 6.1 does not provide the extended features and capabilities that are normally built into a portal server (such as WebSphere Portal). A key feature for a portal is its customizable look-and-feel. In a portal server, customization and personalization are usually handled dynamically through configuration. For example, you can dynamically personalize page themes and skins based on user groups, and you can assign specific user groups permissions to use portlets at runtime. If you want to use these features in Application Server, you have to write them yourself. In addition, aggregation in Application Server is accomplished programmatically using the aggregation tag library. If you want to display multiple portlets in a page, you need to write code to do so using the aggregation tag library. (See the article series "Exploiting the WebSphere Application Server V6.1 portlet container", listed in Resources).

The Tiles framework provides a mechanism to define common layouts for reuse as theme templates in a portal. You combine tiles (as theme templates) and portlet aggregation (as page content) to quickly implement a portal look-and-feel in Application Server. You define page layouts (themes) using the Tiles tag library, and assemble portlets using the portlet aggregation tag library. Then, you link the aggregated portlets to the tiles in the page layout. Both Tiles and portlet tags can take parameters, so you can create a customized look-and-feel, as well as dynamic content.

This article introduces you to integrating Struts Tiles tags and portlet aggregation tags in Application Server to create customized portal pages and a portal look-and-feel. You learn how to:

  1. Create page, menu, and portlet layouts using Tiles tags and portlet aggregation tags.
  2. Use the layouts to create customized pages.
  3. Assemble the layouts into your portal.

The sample code is for demo purpose only. However, you can use the techniques provided in this article to implement a more customer-oriented look-and-feel for your own application. Readers should have a basic knowledge of Tiles, portlets, and portlet frameworks in Application Server V6.1, and know how to create and use them. The portlets used in this article are from IBM and Sun sample JSR 168 portlet code (see Resources). The sample portlets are re-packaged in the WebSphere Application Server Toolkit 6.1 so you can deploy them to Application Server.


Using Tiles and the Portlet Aggregation Framework together

As an example, let's examine a classic portal layout, which consists of header, menu, body, and footer regions (Figure 1). You can think of each region as a tile whose content can be passed as a parameter (a page, page segment, or a string). You can define the menu and body regions as templates in menu layout and body layout, respectively, as shown in Figure 1. The menu layout consists of dynamic pages, each of which links to a different set of portlets aggregated in a portlet layout. You can group sub-pages into a page, organized for a specific purpose. The portlet layout in the body region consists of various numbers of portlets aggregated using the portlet aggregation tags provided in Application Server.

You can create a unique portal look-and-feel in Application Server 6.1 in two ways.

  1. By passing different parameters (page, page segment, strings, or portlets) to the tiles and sub-tiles in the layouts, based on the user who makes a request to customize portal pages.
  2. By changing the layouts, or by using multiple layouts. You can change page layout for a different theme, change portlet layout for a different skin, and change menu layout to modify the placement of the menu.

For example, you might want a top horizontal, rather than a top-down, tree-based page navigation menu. You can always create multiple layouts for use in different pages and for different user groups. For example, you might want administrative portal pages to use different page, menu, and portlet layouts to differentiate their interface from the user interface.

Figure 1. A classic portal layout
Figure 1. A classic portal layout

Creating the portal layout

The following sections show you how to create page, menu, and portlet layouts using Tiles and the portlet aggregation tags, respectively.

Creating a page layout

Page layout provides a common theme for all pages in a portal. Each page in a portal invokes the page layout and passes the parameters (pages or page segments) to the tiles defined in the page layout. Listing 1 shows a classic page layout which inserts five tiles (title, header, menu, body and footer) using the <tiles:insert /> tag in different regions of a table, as shown in Figure 1. The regions occupied by the tiles will be filled by parameters passed in from a calling JSP page.

Listing 1. Classic page layout including tiles for each region
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
	<tiles:importAttribute />
	<html>
	  <head>
	    <logic:present name="title">
	        <title><tiles:getAsString name="title" ignore="true"/></title>
	    </logic:present>    
	  </head>
	  <body>
	    <table border="0" cellspacing="0" cellpadding="0" width="100%" bgcolor="#F8FBFE"> 
	      <tr>
	        <td align="left" colspan="2">  
	            <tiles:insert attribute="header" ignore="true">
	               <tiles:put name="title" beanName="title" beanScope="tile"/>
	            </tiles:insert>
	        </td>   
	      </tr>
	      <tr><td>&nbsp;</td></tr>    
	      <tr>
	        <td valign="top">
	           <ul> 
	              <tiles:insert attribute="menu" />
	           </ul>
	        </td>
	        <td>
	           <div align="center">
	              <tiles:insert attribute="body" />
	           </div>
	        </td>
	      </tr>
	    </table>    
	      <tiles:insert attribute="footer" ignore="true"/>
	  </body>    
	</html>

Creating page navigation

The portal menu displays a list of pages which the user who is currently logged in to the portal can view. Listing 2 shows how to code a menu layout to display a list of page names and links. Each link refers to a set of portlets aggregated in the portal body.

Listing 2. Portal page menu layout
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<tiles:useAttribute id="items" name="items" classname="java.util.List" />   
<logic:iterate id="item" name="items" type="org.apache.struts.tiles.beans.SimpleMenuItem">
   <bean:define id="link" name="item" property="link" type="java.lang.String"/>
   <logic:match name="link" location="start" value="/" >
      <A href="<%=link%>" >
         <bean:write name="item" property="value"/>
   </A>
   </logic:match>
   <logic:notMatch name="link" location="start" value="/" >
       <A href="<%=request.getContextPath()%>/<%=link%>">
         <bean:write name="item" property="value"/>
   </A>
     </logic:notMatch>
     <P/>
</logic:iterate>

The menu layout in Listing 2 uses the Struts logic tag to iteratively display page names and links. The pages and their links are passed in a list (java.util.List) of beans (org.apache.struts.tiles.beans.SimpleMenuItem) by the calling JSP page. If a link that is passed in the bean refers to an absolute URL (starting with "/"), it is copied over and displayed. Otherwise, the link is appended to the page context obtained using request.getContextPath(), and then displayed.

Creating a portlet layout

A portal body contains portlets in various columns and rows. The portlet layout defines a grid of cells, for each portlet in the portal body region. Listing 3 shows the coding for a portlet layout that shows a tabular view of portlet placements in the body region. In the layout, the number of columns in the portal body is passed from calling JSP as a string. The portlet URLs, supported modes for each portlet, and the initial portlet mode are all passed in a list of utility beans (com.jktelecom.PortletInfo) from a calling JSP page. Therefore, a calling JSP page has total control over the number of portlets and the placement, initial mode, and supported modes of each portlet in a page, so you don't have to modify the portlet layout for each portlet.

The portlet layout uses the number of columns and size of the portlet list (both of which are passed by the calling JSP page) to determine the number of rows and cells in which portlets are rendered. The portlet layout iterates through the list in the order originally inserted into the list. It places the supported portlet modes in the <portlet:state> tag, and the portlet URI in the <portlet:insert> tag so that the modes and portlet content can be dynamically rendered to the corresponding cell. The portlet modes, with proper links, will be displayed along with the portlet title, which is retrieved from the portlet deployment descriptor (portlet.xml) by <portlet:insert> tag.

Listing 3. Portlet layout
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="http://ibm.com/portlet/aggregation" prefix="portlet" %>
<%@ page import="java.util.*" %>
<%@ page import="com.jktelecom.*" %>
<%@ page isELIgnored ="false" %>
<%
   String page_uri = (String)session.getAttribute("Current_Page");
   String uri_prefix = PageInfo.getPageName(page_uri) +"/";
%>
<portlet:init portletURLPrefix="<%=uri_prefix%>" >
<tiles:importAttribute />
 <table border="1">  
  <%-- Prepare the links list to be iterated --%>
   <bean:define id="portlets" name="portlets" type="java.util.List" />
   <bean:define id="numColumns" name="numColumns" type="java.lang.String" />
  <%
    int cols = Integer.parseInt(numColumns);
    Iterator loop = portlets.iterator();    
    int portlet_count = 0;
    while (loop.hasNext()) {  
  %>
      <!-- create portal table with number columns defined by variable cols -->
      <tr bgcolor="#e0eaf8">
      <%
        String[] portRefs = new String[cols];  
        for (int i=0; i < cols; i++)  {
          if (!loop.hasNext()) {
          break;
			
          }         
          PortletInfo portletInfo = (PortletInfo)loop.next();          
          portRefs[i] = portletInfo.getName();
          String windowId = String.valueOf(portlet_count);
      %>
          <!-- insert portlet title bar -->
          <td>
            <table width="100%">
              <tr>
                <td>
                  <b><span id="title_<%=portlet_count%>">Portlet <%=
                  portlet_count%></span></b>
                </td>
                <td align="right">
                <%
                  String portletName = portletInfo.getName();
                  String[] portletModes = portletInfo.getSupportedModes(portletName);
                  for (int j=0; j < portletModes.length; j++ )  {
                    %> 
                      <a href="<portlet:state url='<%=portletName%>' 
                      windowId='<%=windowId%>'
                      portletMode='<%=portletModes[j]%>' />">
                      <%=portletModes[j]%> </a>
                      <%
                    }
                   %>           
                &nbsp; &nbsp;
               </td>
			  </tr>
            </table>
          </td>         
      <%
           portlet_count++;
        }
      %>        
     </tr>
     <tr>
      <%
         for (int k=0; k < cols; k++)  {
           int title_num = portlet_count-cols+k;
           String windowId = String.valueOf(title_num);
      %> 
          <td>
            <!-- insert portlet -->
            <portlet:insert url="<%=portRefs[k]%>" windowId="<%=windowId%>" 
              titleVar="title" />
          </td>          
          <!-- insert portlet title -->          
          <script type="text/javascript">
   document.getElementById("title_<%=title_num%>").firstChild.nodeValue = "${title}";
          </script>
      <%
        }     
      %>     
     </tr>
     <tr><td colspan="<%=cols%>">&nbsp;</td></tr>
  <%
   }
  %>   
 </table>
</portlet:init>

You need to address the following issues in the portlet layout, as seen in Listing 3.

Setting the URL prefix

You need to specify a proper URL prefix for the portletUrlPrefix attribute in the init portlet aggregation tag.

The prefix is used in portlet URLs created by the state and insert tags. It consists of two parts: aggregation context and aggregator mapping. If you use a relative path for the URL, the portlet container will take care of the aggregation context for you. However, if you use an absolute path for the URL (for example, /jkTelecom/Tools/), when you deploy your portal application (WAR) to Application Server, you must specify the same context root (jkTelecom) that you used in the aggregation context. You must configure the aggregation mapping part in the URL in the Web application deployment descriptor (web.xml) to point to the URL referenced by the current page, which displays the portlet aggregation (portlet layout).

For example, if the current portlet aggregation is invoked by the Tools page, which refers to tools.jsp, then the portlet URL must map to tools.jsp You will learn the details about the mapping below in the Portal configuration section.

To set proper aggregator mapping, you must track the page the user is currently reviewing and set the aggregation mapping accordingly. The sample code handles the tracking as follows:

  1. When a user clicks a page link from the menu, the code stores the page URL in the user’s session (for example, tools.jsp):
    <%
      String current_page = "tools.jsp";   
      session.setAttribute("Current_Page", current_page);
    %>
  2. It retrieves the URL from the session in the portlet layout (portletLayout.jsp).
    <%   
      String page_uri = (String)session.getAttribute("Current_Page");
      String uri_prefix = PageInfo.getPageName(page_uri) +"/";
    %>
  3. It obtains the mapping for the URL from a map defined in the PageInfo.java class (Listing 4). The utility class, PageInfo.java, contains all the mappings to URLs which correspond to the mapping in web.xml.

    Listing 4. Page mappings

    static HashMap pages;
    static {
    	pages = new HashMap();
    	pages.put("index.jsp", "Home");
    	pages.put("account.jsp", "Account");
    	pages.put("tools.jsp", "Tools");
    	pages.put("reports.jsp", "Report");
    	pages.put("services.jsp", "Services");
    	...
    }
    public static String getPageName(String uri) {      
    	return (String)pages.get(uri);
    }
  4. Finally, the aggregator mapping is assigned to the portletURLprex attribute of the init tag of the portlet aggregator.
    <portlet:init portletURLPrefix="<%=uri_prefix%>"

Handling portlet mode

Each portlet normally supports different modes (such as view, edit, and help) whose icons are usually displayed along with the portlet title in a portal. You must know what modes a portlet supports before displaying the icons. Otherwise, either a supported mode is missing from your portlet (if you don’t display the icon for the mode), or an exception will be thrown (if the displayed mode is not supported by the portlet).

Portlet mode information is available in the <supports> section of the portlet deployment descriptor (Listing 5).

Listing 5. Portlet deployment descriptor (portlet.xml) fragment
<supports>
	<mime-type>text/html</mime-type>
	<portlet-mode>config</portlet-mode>
	<portlet-mode>edit</portlet-mode>
	<portlet-mode>help</portlet-mode> 
</supports>

Unlike portlet title, which can be retrieved using the portlet aggregation tag <portlet:insert>, no portlet aggregation tag is available to help you retrieve the supported modes. You must view the portlet deployment descriptors to retrieve them yourself. Supported modes for all the portlets used in the sample code are stored in a hash map, so that they can be retrieved dynamically (Listing 6):

Listing 6 Supported portlet modes
static HashMap supportedModes;
static {
	supportedModes = new HashMap();
	supportedModes.put("IBMSamples/HelloWorld", new String[]{"view"});
	supportedModes.put("IBMSamples/WorldClock", new String[]{"view", "edit", "help"});
	supportedModes.put("IBMSamples/SQLQuery", new String[]{"view"});    
	supportedModes.put("IBMSamples/HelloJSP", new String[]{"view"});
	supportedModes.put("SunSamples/JSPPortlet", new String[]{"edit", "help"});
	supportedModes.put("SunSamples/NotepadPortlet", new String[]{"edit", "help"});
	supportedModes.put("SunSamples/BookmarkPortlet", new String[]{"edit", "help"}); 
}
public String[] getSupportedModes(String portletName) {
	return (String[])supportedModes.get(portletName);
}

Assembling the portal

In this part, you see how to write JSPs to use the page, menu, and portlet layouts to create tailored portal pages. You also see how to configure the Web application descriptor (web.xml) to support portlet aggregation mappings.

Using the page layout

The calling JSP page passes parameters to be inserted into the page layout. A parameter can be another JSP page, a page segment, or a simple string, depending on the current user and the content to be displayed to the user.

Listing 7 shows the coding for a default page layout definition that specifies default parameters passed to the page layout. For example, the header.jsp file is passed to the header tile, and the footer.jsp file is passed to the footer tile in the page layout.

Listing 7. Default page layout definition
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<logic:notPresent name="pageLayoutDef" scope="request" >
 <tiles:definition id="pageLayoutDef" page="/pageLayout.jsp" scope="request" >
  <tiles:put name="title" type="string" value="jkTelecom Portal" /> 
  <tiles:put name="header" value="/header.jsp" />
  <tiles:put name="footer" value="/footer.jsp" />
  <tiles:put name="body" value="/default_body.jsp" />   
  <tiles:put name="menu" value="/default_menu.jsp" />                
 </tiles:definition>
</logic:notPresent>

A calling JSP page can also override the default behavior defined in the page layout definition by passing different parameters. In Listing 8, a calling JSP page (tools.jsp) uses the page layout definition in Listing 7; it overrides the default menu page (default_body.jsp) and body page (default_menu.jsp) using menu.jsp and portlets.jsp.

Listing 8. A portal page (tools.jsp) which uses the page layout
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%
	String current_page = "tools.jsp";   
	session.setAttribute("Current_Page", current_page);
%>
<jsp:include page="/pageLayoutDef.jsp" />
<tiles:insert beanName="pageLayoutDef" flush="true" beanScope="request">
	<tiles:put name="body" value="/portlets.jsp" />  
	<tiles:put name="menu" value="/menu.jsp" />
</tiles:insert>

Using page navigation

Listing 9 shows a portal menu (menu.jsp) using the menu layout. The portal menu uses jsp:useBean to create an instance of SimpleMenuItem. Then, it uses jsp:setProperty to set the link and value properties of the SimpleMenuItem bean. Finally, it adds the bean to the list using tiles:add.

The menu is customized on a user group basis to create role-based pages without modifying the menu layout. Therefore, a page is visible only if the user is in a specific role and has permission to the page. The user role is determined by the isUserInRole method of the request object.

Listing 9. A portal page menu which uses the menu layout
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<tiles:importAttribute />
<tiles:insert page="/menuLayout.jsp" flush="false" > 

   <tiles:putList name="items" >
    <jsp:useBean id="item_0" class="org.apache.struts.tiles.beans.SimpleMenuItem" />
    <jsp:setProperty name="item_0" property="link" value="index.jsp" />
    <jsp:setProperty name="item_0" property="value" value="Home" />               
    <tiles:add beanName="item_0" />
	...	
<%
	if (request.isUserInRole("Managers")){
%>    
	<jsp:useBean id="item_4" class="org.apache.struts.tiles.beans.SimpleMenuItem" />
	<jsp:setProperty name="item_4" property="link" value="tools.jsp" />
	<jsp:setProperty name="item_4" property="value" value="Tools" />
    <tiles:add beanName="item_4" />
        ...	  
   <%

	} else if (request.isUserInRole("Users"))  {  
%>   
	<jsp:useBean id="item_8" class="org.apache.struts.tiles.beans.SimpleMenuItem" />
	<jsp:setProperty name="item_8" property="link" value="services.jsp" />
	<jsp:setProperty name="item_8" property="value" value="Services" /> 
	<tiles:add beanName="item_8" />
	  ...			
   <%
	}			
   %> 
  </tiles:putList> 
</tiles:insert>

Using the portlet layout

Listing 10 shows a JSP page (menu.jsp) which uses the menu layout. The number of columns in which portlets are rendered in the body, and a list of beans (com.jktelecom.PortletInfo) created by <jsp:useBean> are passed to the portlet layout. The bean contains all the information (portlet URL, initial mode, and supported modes) the portlet layout needs to render the portlets.

Listing 10. A JSP page which uses portlet layout
<%@ taglib uri="/WEB-INF/struts-tiles.tld" prefix="tiles" %>
<%@ page import="java.util.*" %>
<%@ page import="com.jktelecom.*" %>
<tiles:insert page="/portletLayout.jsp" flush="false" >    
    <!-- create portal table of two columns -->
<%
    if (request.isUserInRole("Managers"))  {
%> 
      <tiles:put name="numColumns" value="3" />
<%
    } else {
%>    
         <tiles:put name="numColumns" value="2" />
<%
    }
%>         
    <!-- pass portlet links -->   
    <tiles:putList name="portlets" >
       <jsp:useBean id="portlet_0" class="com.jktelecom.PortletInfo" />
       <jsp:setProperty name="portlet_0" property="name" 
         value="IBMSamples/HelloWorld" />
       <jsp:setProperty name="portlet_0" property="initialMode" 
         value="<%=PortletInfo.VIEW%>" />
       <tiles:add beanName="portlet_0" />      
    <%
      if (request.isUserInRole("Managers"))  {
    %>     
         <jsp:useBean id="portlet_1" class="com.jktelecom.PortletInfo" />
         <jsp:setProperty name="portlet_1" property="name" 
           value="SunSamples/JSPPortlet" />
         <jsp:setProperty name="portlet_1" property="initialMode" 
           value="<%=PortletInfo.EDIT%>" />
         <tiles:add beanName="portlet_1" />
         …
    <%
      } else if (request.isUserInRole("Users"))  {      
    %>
         <jsp:useBean id="portlet_6" class="com.jktelecom.PortletInfo" />
         <jsp:setProperty name="portlet_6" property="name" 
           value="IBMSamples/WorldClock" />
         <jsp:setProperty name="portlet_6" property="initialMode" 
           value="<%=PortletInfo.VIEW%>" />
         <tiles:add beanName="portlet_6" />
         …
    <%
      }
%>              
     </tiles:putList>       
</tiles:insert>

As shown in Listing 8, the number of columns and the list of portlets are set on a role basis. You can also control permissions to the portlets from your calling JSP. You can implement these customizations in several ways:

  1. A portlet is visible to a user only if the user is in certain role and has permission to it; therefore, you can selectively pass portlets to the portlet layout for a specific user or user group. Users without permissions to the portlets will not see them in their portal.
  2. You can further limit available supported modes of a portlet for certain users or groups for a finer-grained control of privileges. For example, you might choose to block the anonymous user’s ability to edit the portlet by only displaying the edit icon to authenticated users.
  3. You can pass the number of portlets and the number of columns to the portlet layout without modifying the portlet layout.

Configuring the portal

When integrating multiple pages which contain portlets into a portal, you need to take special actions to handle the portlet URL. When a user clicks on a different portlet mode, all other portlets as well as the entire page are refreshed, and form data in the portlet is re-posted.

  1. When you use the aggregation tag library, you must set the portletUrlPrefix attribute of the init tag to the proper aggregator context and mapping. The aggregator context is the context root of the current application. The aggregator mapping must reference the current page, as described in the portlet layout section above.
  2. You need to define mappings for all the portal pages in the application deployment descriptor (web.xml) so that the aggregator mappings reference valid JSP pages (Listing 11). The mappings defined in web.xml are available in the utility class PageInfo.java so the mappings can be retrieved directly.
Listing 11. Portal application deployment descriptor (web.xml)
…
<servlet>			
    <servlet-name>Home</servlet-name>
    <jsp-file>index.jsp</jsp-file>
</servlet>
<servlet>			
    <servlet-name>Tools</servlet-name>
    <jsp-file>tools.jsp</jsp-file>
</servlet>
…
<servlet-mapping>
   <servlet-name>Home</servlet-name>
   <url-pattern>/Home/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
   <servlet-name>Tools</servlet-name>
   <url-pattern>/Tools/*</url-pattern>
</servlet-mapping>
…

In Listing 11, a JSP page (index.jsp) is defined as an implementation of an imaginary servlet Home. The aggregation mapping pattern /Home/* is referred to the Home servlet. A URL with the pattern /Home/* will dynamically resolve to the JSP page (index.jsp). This mapping relationship is shown in the Figure 2, which illustrates how the mappings from web.xml are shown in the URLs for links to portlet mode icons.

For example, when a relative URL Home is specified to an aggregator mapping in the portletUrlPrefix attribute of the init tag (jkTelecom is the context root), the aggregation pattern /Home/ will be resolved as index.xml. When a user clicks any icon (view, edit, and help) for a portlet in the page, the form data in the portlet mode requested is re-posted, and the entire page, including all other portlets, is refreshed as well. Figure 2 illustrates this mapping relationship.

Figure 2. Mapping relationship
Figure 2. The mapping relationship

Deploying the portal

You package the application as a WAR file and deploy it as any Web application. Figures 3 and 4 show the deployed portal for the example code. The context root is specified as jkTelecom. If you use a relative path for the PortletUrlPrefix attribute in the init tag (as discussed in the portlet layout section), you can use any string as the context root. Otherwise, you must specify the same context root as you used in the aggregation context.

Figure 3. Deployed portal with user sara in the "Managers" role
Figure 3. Deployed portal with user sara in the Managers role
Figure 4. Deployed portal with user fred in the "Users" role
Figure 4. Deployed portal with user fred in the Users role

Conclusion

Now you know how to create common portal layouts (page, navigation, and portlet layouts) as reusable templates using Struts Tile tags and portlet aggregation tags. You can use the layouts to create dynamic web pages, and you can assemble the layouts into a portal. You have seen how to address various development and deployment issues to ease the development effort. Now you can apply the information presented here to create your own portal pages using the WebSphere Application Server portlet container and aggregation tags.


Download

DescriptionNameSize
Code sampleswebportal-samples.zip1990 KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=200408
ArticleTitle=Rapidly implementing portal look-and-feel using Struts Tiles and the Portlet Framework in WebSphere Application Server V6.1
publish-date=03072007