Skip to main content

Modeling WebSphere Portal Portlets with UML: Part 1

Anthony Bernal (abernal@us.ibm.com), Sr. IT Specialist -- Portal SWAT Team, IBM eWorkplaces/Knowledge and Content Management
Photo: Joey Bernal
Anthony (Joey) Bernal is a Senior I/T Specialist with the e-Workplaces/Knowledge and Content Management Practice with IBM Global Services. You can reach Joey at abernal@us.ibm.com.

Summary:  Design portals and portlets using the Unified Modeling Language (UML). Using basic portal design practices and UML, this article provides a design framework for a simple Portlet-MVC design upon which you can build your own portlet applications.

Date:  11 Sep 2002
Level:  Intermediate
Activity:  727 views

Introduction

With the increased popularity of portals on the Web, and organizations continuing to choose IBM ® WebSphere® Portal as their primary platform, we as a community need to quickly develop a set of reusable assets and work products that allow us to effectively design and develop portal applications. Architects and developers alike are struggling with design issues surrounding building applications to best take advantage of the framework WebSphere Portal provides.

I have often thought that what is needed is a series of models or patterns for describing portlets and their use in applications. This article articulates one approach for designing portals and portlets using the Unified Modeling Language (UML). Using basic portal design practices and UML, I provide a design framework for a simple Portlet-MVC design upon which you can build your own portlet applications. Hopefully this can be the start of a set of models for portlet designs upon which we can begin to build a set of patterns for reuse.

This article is not about coding portlets. While I present code samples which help to illustrate the UML model and design, most of the code has been stripped down to the bare essentials to focus on the design itself. Any robust application will require much more error checking and exception handling than is provided here.


Why model Portal applications?

Why should we model Portal Applications? It's actually a good question. Usually we think of a portal as a group of small, discreet pieces of functionality or content. I don't need to go to all the trouble of modeling those, do I? The marketing hype tells us that building portlets are easy, with simple portlets being built in a few hours to a few days. If this is the case, we hardly need to invest the time for a major requirement and design phase, do we? Well actually, yes! If it is really the case that a portal requires only one or two portlets that provides some discreet functionality, or access to a legacy system, then it is probably not necessary for a large upfront investment in time and people to do a complete design. A few days, to a week of design time would probably be sufficient. Or perhaps you could consider another approach, such as using an evolved prototype or extreme programming.

Unfortunately while the WebSphere Portal framework does greatly reduce our design and development time, and provides us with an extensible set of functionality, it is no silver bullet. Most major portal applications require more than a simple portlet or two. At minimum there will be a "set" of portlets or even several sets, providing the required functionality. Additionally you need utility classes, singletons, tag libraries and services that provide underlying access to a wide variety of services and systems. And let's not forget EJBs for high volume transactional systems. Larger systems of this nature require a dedicated design cycle following a proven design methodology. The one proposed in this article using UML is still evolving, even as WebSphere Portal itself continues to evolve.


Setting the stage

The scenario presented here is quite simple. I will describe and model a simple portlet that provides basic CRUD (Create, Read, Update, Delete) functionality for a given problem. The approach taken is pretty generic. It is designed to show the basics of how a system of this type could be modeled using UML, and not to overwhelm you with examples of functionality. Most architects and designers will encounter dozens of examples of this type of portlet functionality during their career, and should be able to easily extend the ideas presented here to reflect a real world scenario.

With that in mind, we can pretend to operate on a simple object of type "Item", or perhaps a list of "Items". What "Item" actually is we aren't really interested in. It can be a set of users, customers, accounts, houses, computers, or whatever.

Building use cases

Gathering requirements using use cases can be tricky. They can only be done well by people experienced in use case Modeling. Generally, technical people who understand UML and use-case modeling have trouble looking at a use case from the user point of view. They are always trying to design the system at the same time as requirements are being gathered. Non-technical folks such as consultants and business analysts who understand how to build effective use cases are very rare and worth their weight in gold. These people can talk the customer's language and build effective use cases that truly reflect the business requirements.

CRUD functionality isn't always at the top of the list when it comes to design. Usually it is basic table maintenance that doesn't have a major impact on the application, so it doesn't appear to add a lot of value to the actor and is not often considered a primary use case. I believe, however, that it is one of the most common types of functionality that you will encounter and is fairly easy to understand. Being familiar with the requirements will help you not to get bogged down in the requirement details and allow you to focus on the model and the design approach.

Trying to achieve the right level of granularity for use cases can also be an issue. In a very coarse-grained system we could create one use case named "Manage Item". This is probably a little too simple for any useful analysis. It might be better to decompose this into a more complete set of use cases. To illustrate our sample portlet I have created a simple package named "ManageItems" which includes the following four uses cases:

  1. Search Items: Search for an item or a list of items.
  2. Adds Item: Add a new item to our application.
  3. Delete Item: Delete an item from our application. Usually performed after a search.
  4. Edit Item: Edit an item in our application. Usually performed after a search.

Figure 1 illustrates these use cases using a use case diagram. The actor provided here is a simple user who interacts on all four of the cases. I've also provided some additional detail such as a login case that is included by all other use cases. I haven't provided much detail for the sample use cases; they are pretty self-explanatory in what functionality they describe.


Figure 1. Use cases
Use cases

The next step is to flush out each of the use cases and begin to further model the system. You can identify nouns and verbs based on the gathered functionality, and design interaction and activity diagrams. For our example we will only follow one of the cases and examine it in detail. We begin with the Search Items use case. Since all the cases are already present in the model, we can return to this view after we finish with the Search Items case and continue to model the next use case.

Activity and interaction diagrams

Activity between the user and the system can be described in several ways. Figure 2 shows an activity diagram of the SearchItems use case. This diagram is presented from the viewpoint of a user interacting with the system. This simple diagram, also known as a "swim lane" diagram, is a start to identifying components within the system. In this diagram we are viewing System as a single component. Further decomposition lets us start identifying additional objects that can be modeled into classes, and other objects within the design.


Figure 2. Activity diagram with swim lanes
Activity diagram with swim lanes

Further interaction with the system either through interaction diagrams or collaboration diagrams can be used to expand the design and help derive additional objects and interactions (nouns and verbs) that are used in the model. Modeling and decomposition of this type require a solid background and understanding of UML and its use. This article only attempts to put UML into a proper context for designing portlets.


Creating class diagrams

Fortunately we are building a WebSphere Portal portlet. Because of this, and the framework that WebSphere Portal provides, it is pretty easy to derive a component layout for the final portlet. We need to be smart in our design and ensure that it is taking full advantage of the framework correctly. But the portlet design can also build upon the effort of other excellent designers and follow the published API for WebSphere Portal.

To lay out the classes necessary for our portlet we can follow the basic Model-View-Controller pattern that is recommended by the framework. Figure 3 shows the basic class diagram for the Manage Items portlet. The classes in Figure 3 provide a basic layout for this and a lot of the other portlets that you may encounter when building your own portal applications. The Manage Items portlet configured in this manner can incorporate all of the use cases that were entered into the use case diagram described earlier.


Figure 3. Portlet class diagram
Portlet class diagram

The initial diagram provides for three primary classes. Let's take a look at each class in turn with some code examples.

PrimaryHTMLController.class

This is the primary class for the portlet and inherits from the PortletAdaptor class provided by the WebSphere Portal API. Taking a lightweight controller approach to designing the portlet, this class is primarily a lightweight object containing very little business logic. The methods within the class are standard methods outlined for all portlet controller classes.

 
 
package com.ibm.wps.manageitems; 
 
import java.io.*; 
import java.util.*; 
import com.ibm.wps.engine.*; 
import org.apache.jetspeed.portlet.*; 
import org.apache.jetspeed.portlet.event.*; 
import org.apache.jetspeed.portlets.*; 
 
public class ManageItemsPortletHTMLController extends PortletAdapter 
        implements PortletTitleListener, ActionListener { 
 
	public void init(PortletConfig portletConfig) throws UnavailableException { 
		super.init(portletConfig); 
	} 
 
	public void doTitle(PortletRequest request, PortletResponse response) { 
	} 
 
			

The actionPerformed() method performs a lot of the controller logic for this portlet. In this example the method is a series of if statements that divert control to different locations within our utility class.

 
 
	public void actionPerformed(ActionEvent event) { 
 
		PortletRequest request = event.getRequest(); 
		PortletSession session = request.getPortletSession(); 
		PortletAction _action = event.getAction(); 
		DefaultPortletAction action; 
 
		if (_action instanceof DefaultPortletAction) { 
 
			action = (DefaultPortletAction)_action; 
 
			// Handle ACTION events 
			if (action.getName().equals(ManageItemsUtil.ACTION_SEARCH)) { 
 
				bean = ManageItemsUtil.searchItems(this, request); 
				session.setAttribute(ManageItemsUtil.TARGET_PAGE, 
                      ManageItemsPortletUtil.JSPSEARCHRESULTS); 
				session.setAttribute("ManageItemsBean", bean); 
 
			} 
			else if (action.getName().equals(ManageItemsUtil.ACTION_CREATE)) { 
 
				bean = ManageItemsUtil.createItem(this, request); 
				session.setAttribute(ManageItemsUtil.TARGET_PAGE, 
                                    ManageItemsUtil.JSPConfirm); 
				session.setAttribute("ManageItemsBean", bean); 
 
			} 
			else if (action.getName().equals(ManageItemsUtil.ACTION_SAVE)) { 
 
				bean = ManageItemsUtil.saveItem(this, request); 
				bean.clearErrors(); 
				bean.clearValues(); 
				session.setAttribute(ManageItemsUtil.TARGET_PAGE, 
                                    ManageItemsUtil.JSPSaveResults); 
				session.setAttribute("ManageItemsBean", bean); 
			} 
		} 
	} 
 
			

The doView() method displays various JSPs that are used in our portlet for user input and to display results. It acts as a controller method that sets up and then displays the correct JSP. The JSP to be displayed is determined by the actionPerformed() method above.

 
 
	public void doView(PortletRequest request, PortletResponse response) 
                      throws PortletException, IOException { 
 
		PrintWriter writer = response.getWriter(); 
		PortletContext context = getPortletConfig().getContext(); 
		PortletSession session = request.getPortletSession(); 
		ManageItemsBean bean = null; 
 
		// Set initial jspName to JSPMain. 
		// Use this as the default if TARGET_JSP 
		String displayJsp = null; 
		String jspPrefix = "/jsp/"; 
		String jspName = ManageItemUtil.JSPMain; 
		String tempJsp = (String) session.getAttribute(ManageItemsUtil.TARGET_PAGE); 
 
		if (tempJsp != null) { 
			displayJsp = jspPrefix + tempJsp; 
		} else { 
			displayJsp = jspPrefix + jspName; 
		} 
 
		try { 
 
 
			// Extract ManageItemsBean from session 
			bean = (ManageItemsBean) session.getAttribute("ManageItemstBean"); 
 
			// Keep the bean from session if it exists 
			if (bean != null) { 
 
			} else { 
 
			// Instantiate a new bean if it doesn't already exist 
 
} 
				bean = ManageItemsUtil.initItemsBean(this, request); 
			} 
 
			// Put the bean back into session 
			session.setAttribute("ManageItemsBean", bean); 
 
			// Delegate the rendering to displayJsp 
			context.include(displayJsp, request, response); 
 
			// Log debug information 
			if (getPortletLog().isDebugEnabled()) { 
				getPortletLog().debug("++++ Set display JSP to " + displayJsp); 
			} 
		} catch (Exception ex) { 
 
			getPortletLog()Debug(ex.getMessage()); 
			ex.printStackTrace(System.out); 
		} 
	} 
 
	public void doHelp(PortletRequest request, PortletResponse response) 
       throws PortletException, IOException { 
	} 
 
	public void doEdit(PortletRequest request, PortletResponse response) 
       throws PortletException, IOException { 
	} 
 
	public void doConfigure(PortletRequest request, PortletResponse response) 
       throws PortletException, IOException { 
	} 
 
} 
			

PortletUtility.class

The manageItemsUtil class implements a few basic utility functions that are needed by the other classes and some JSPs. It also abstracts most of the business logic needed for the portlet. It will do this either by including business logic itself into its methods, or by handing the logic off to another helper class, portlet service, or an EJB.

 
 
package com.ibm.wps.manageitems; 
 
import java.io.*; 
import java.util.*; 
Import java.text.*; 
Import org.apache.jetspeed.portlet.*; 
Import org.apache.jetspeed.portlet.event.*; 
Import org.apache.jetspeed.util.*; 
 
public class ManageItemPortletUtil { 
 
	public final static String ACTION_CREATE = "createItemAction"; 
  	public static final String ACTION_DELETE = "deleteItemAction"; 
  	public static final String ACTION_EDIT = "editItemAction"; 
  	public static final String ACTION_SEARCH = "searchItemAction"; 
  	public static final String ACTION_SAVE = "saveItemAction"; 
 
	public static final String JSP_ADD = "AddItem.jsp"; 
	public static final String JSP_CONFIRM = "ConfirmItem.jsp"; 
	public static final String JSP_EDIT = "EditItem.jsp"; 
	public static final String JSP_MAIN = "Index.jsp"; 
	public static final String JSP_SEARCH_RESULTS = "SearchResults.jsp"; 
	public static final String JSP_SAVE_RESULTS = "SaveResults.jsp"; 
 
	public static final String CALLING_PAGE = "callingPage"; 
	public static final String TARGET_PAGE = "targetPage"; 
 
			

The getNewActionURI() method is used primarily by the JSPs within the portlet to create return and action URIs within a JSP page. There are two versions of this method: a single URI version shown first, and a second version that allows for a parameter to be passed with the URI.

 
 
	/** 
	 * Method: getNewActionURI(PortletResponse, String) 
	 * Return: String 
	 * Description: Build an action URI 
 	 */ 
	public static String getNewActionURI(PortletResponse request, 
                 String actionName) { 
 
		PortletURI portletURI = request.createReturnURI(); 
		DefaultPortletAction action = new DefaultPortletAction(actionName); 
		portletURI.addAction(action); 
		return portletURI.toString(); 
  	} 
 
 
	/** 
	 * Method: getNewActionURI(PortletResponse, String, String, String ) 
	 * Return: String 
	 * Description: Build an action URI with additional parameters 
 	 */ 
	public static String getNewActionURI(PortletResponse request, 
                 String actionName, String Param, String Value) { 
 
		PortletURI portletURI = request.createURI(); 
		PortletAction portletAction = new DefaultPortletAction(actionName); 
		portletURI.addAction(portletAction); 
		portletURI.addParameter(Param, Value); 
		return portletURI.toString(); 
	} 
 
			

The initManageItemsBean() method is an optional method that can be used to initialize the portlet bean if necessary. This method is not required if your bean is very simple.

 
 
	Public static ManageItemsBean initManageItemsBean(PortletAdapter portlet, 
                                                     PortletRequest request) { 
 
		ManageItemsBean bean = new ManageItemsBean(); 
 
		//initialize bean here if necessary 
 
		return bean; 
 
	} 
 
			

The searchItems() method is provided here as an example of where business logic could be placed in this type of portlet. The idea is to keep the controller class as simple as possible to allow business logic to be abstracted to a helper class. This method can implement the business logic itself, or it can access a portlet service or EJB if required. Additional methods of this type will be necessary for a portlet implemented with complete functionality.

 
 
	Public static ManageItemsBean searchItems(PortletAdapter portlet, 
                                              PortletRequest request) { 
 
		ManageItemsBean bean = new ManageItemsBean(); 
 
		//business logic goes here! 
 
		return bean; 
 
	} 
} 
 
			

PortletBean.class:

The bean is used as our primary storage and communication device with the JSP. We cache the bean in the PortletSession for the life of the portlet instance, and the portlet updates the data within the bean as necessary. Since the portlet is being designed using a Model 2 JSP Architecture, the bean plays an important role in our design. In Figure 3 above, I have included a set of getters and setters to simulate what would probably be needed to implement the search functionality we are discussing. Those getters and setters should be modified for your own implementation.


Adding JSPs and HTML pages

With core classes and interactions in place, we can take a look at the presentation layer necessary to complete our portlet. As mentioned earlier, the example follows a familiar Model-View-Controller approach taking full advantage of J2EE best practices in developing Web applications. JSPs play a major role in that approach.

Since JSPs are a hybrid between HTML and the Java language, it can be difficult to attain complete separation of the presentation layer. Some opportunity usually presents itself to sneak some business logic into a JSP. There isn't a perfect way to keep this from happening in a development effort. A good design can help to avoid it, but even the best designs can't cover every contingency or scope change. Experienced developers who understand the concepts of proper development as well as the language itself can help to ensure that any business logic that does appears within a JSP is limited and properly designed.

For our example we will add two JSP pages. Notice in Figure 4, that for each JSP added to the model we also added an associated HTML page. This association allows us to illustrate in our model a separation between server and client-side interaction. For the Manage Items portlet we have added the following pages:

Main.jsp
This is the main JSP that is displayed by default. The sample code for the doView() method shows an example of setting up the TARGET_PAGE to display this page if no other page is set in the actionHandler() method.
Main.html
This is the client side version of the Main.jsp. Included in this page is a search form that triggers the search action. The action from this page triggers the actionPerformed() method to initiate a search.
SearchResults.jsp
This JSP gets the results from the search action in the form of a Java bean and formats the corresponding HTML page to display the search results.
SearchResults.html
This is the client side display of the search results.

Expanding the original class diagram to use these new pieces of functionality provides us a better overview of the full functionality of our portlet. In the new class diagram, (Figure 4) we see a complete picture of all the components used for the search functionality for our portlet.


Figure 4. Search class diagram
Search class diagram

While a class diagram allows us to see objects from a component view, it does not provide a complete view of the sequence of events that will take place in our portlet. We can see better detail for the search function with a sequence diagram showing how the search action takes place. Figure 5 gives a picture of how our components will actually interact with one another during the search process. Notice that we use method names, stereotypes and common English to describe the interactions between objects.


Figure 5. Search sequence diagram
Search sequence diagram

English text interactions such as "Determine Action" can be decomposed down to a very fine level of detail, captured into a second design document or work product, or handed off to a developer to complete during implementation. There are no rules as to the level of detail that your models have to follow, and the effort and level of detail involved should be reflective of the nature of the functionality and the size of the project.

Sample JSP code

When designing a JSP, we should take advantage of the framework we used to set up our portlet controller and other classes. In our design we depend upon a Java bean to provide us with any information we need to display within the JSP. Making this assumption we can just look to the bean. When coding JSPs, start by importing any packages that will be needed. This includes adding your portlet package since we will be accessing the manageItemsUtil() class. Also any needed tag libraries should be included here.

Tag libraries and portlet services can be modeled in your class diagrams similar to the way that Java beans and utility classes are modeled. If you have developed custom tag libraries that you want to include and model with JSP components, they can be set up in your class diagram using an include stereotype. Before you start to work with these items, you should look at all of your portlets and coalesce similar classes into services and libraries.

 
 
<%@ page import="org.apache.jetspeed.portlet.service.*" %> 
<%@ page import="org.apache.jetspeed.portlet.*" %> 
<%@ page import="org.apache.jetspeed.portletcontainer.PortletRequestImpl" % > 
<%@ page import="org.apache.jetspeed.portlet.*" %> 
<%@ page import="com.ibm.wps.engine.RunData" %> 
<%@ page import="com.ibm.wps.manageitems.*" %> 
<%@ page import="com.ibm.wps.services.authorization.*, 
    com.ibm.wps.puma.*,com.ibm.wps.util.*" %> 
<%@ taglib uri="/WEB-INF/tld/portlet.tld" prefix="portletAPI" %> 
<portletAPI:init/> 
 
<jsp:useBean id="ManageItemsBean" 
     class="com.ibm.wps.manageitems.ManageItemsBean" scope="session" /> 
 
			

When you've set up the headers within a JSP, you can create an action handler URI similar to the following example. This example creates an ACTION_CREATE link. When called, it triggers that section of the actionPerformed() method coded to recognize this parameter. The action handler will then perform whatever action is required, and set the TARGET to the next JSP to display.

 
 
<a href="<%= ManageItemsUtil.getNewActionURI(portletResponse, 
             ManageItemsUtil.ACTION_CREATE) %>">Add Item</a> 
 
			

You can create the search form in the model using the following code sample. It also uses an action handler URI, and encodes form parameters using the portlet tag library. This library isn't modeled in our system because it is part of the supplied API for WebSphere Portal. Modeling components that are already supplied within WebSphere Portal is possible, but can add to the complexity of the model. You should only go to this level of detail in cases where you really want to show particular detail about using a particular API.

 
 
<form name="itemsearchform" 
  action="<%= ManageItemUtils.getNewActionURI(portletResponse, 
              ManageItemsUtil.ACTION_SEARCH) %>" method="post"> 
 
<table border="0" cellpadding="3" cellspacing = "3"> 
<tr> 
<td align="left">Customer ID:</td> 
<td align="left"> 
<input type="text" name="" value="<%= ManageItemBean.getItemName() %>"> 
</td> 
</tr> 
<tr> 
<tr> 
<td align="right"> 
<input type="submit" name="" value="" />"> 
<br> 
</td> 
</tr> 
</table> 
</form> 
 
			


Development, deployment and beyond

Even with only a single model in place, moving to micro design and development for this piece of functionality is a much easier process. After all the major components in a system (or in our case subsystem) are fully designed and coalesced, developers can see, not only what, but how specific objects should best be implemented. Changes identified during development can be transcribed within the model and reflected throughout the system.

In Figure 6 I have laid out the package structure (within the modeling tool) of the objects, similar to how I might expect them to be created during development. This approach helps to group connected items together in a format similar to how they are developed, and eventually deployed onto the target system.


Figure 6. Model browser
Model browser

Used in combination with other work products such as wire frame models and design documents, UML can be a powerful way to communicate requirements and design to developers. The code samples provided above provide you with an example of the objects being modeled. They also hopefully provide some examples of best practices for portlet development using JSPs and utility classes. In closing, I hope to have provided enough information for you to start using UML when designing your own portal applications. In future articles I will try and build upon what has been presented here to include modeling portlet services and extend the portlet classes to take advantage of these services.

Top of page


Resources

About the author

Photo: Joey Bernal

Anthony (Joey) Bernal is a Senior I/T Specialist with the e-Workplaces/Knowledge and Content Management Practice with IBM Global Services. You can reach Joey at abernal@us.ibm.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=13962
ArticleTitle=Modeling WebSphere Portal Portlets with UML: Part 1
publish-date=09112002
author1-email=abernal@us.ibm.com
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers