Improving the performance of WebSphere Portal applications using the expirable properties portlet service

This article describes, and shows how to use, a portlet service to extend the caching options available to portal application developers. The expirable properties portlet service (hereafter called EPPS) works as a central caching system for portlets running under IBM® WebSphere® Portal. You can use it to improve the performance of portal applications, by caching elements used within a portlet. The EPPS provides dynamic, fine-grained control of items to be cached. This article includes the code for this portlet service, and a sample application which illustrates how to use it.

Hongqing Song (song@us.ibm.com), WebSphere Consultant, IBM Dallas, eServer Solutions Enablement

Hongqing Song has been a WebSphere consultant since 2000. He provides WebSphere consulting services across the nation. Hongqing Song can be reached at song@us.ibm.com.



Richard Scott (rmscott@us.ibm.com), Architect, IBM Dallas, eServer Solutions Enablement

Richard Scott is an Architect and Technical Lead in IBM Dallas, eServer Solutions Enablement. He can be reached at rmscott@us.ibm.com.



06 October 2004

Introduction

When you design a J2EE application or portal application, a major thing to consider is performance. Caching is often used to improve performance, and WebSphere Portal has a built-in caching feature. When you develop a portlet, you can define the caching policy for the portlet in its portlet.xml.

Listing 1. Specifying a caching policy for a portlet
<cache>
  <expires>number</expires>
  <shared>yes|no</shared>
</cache>

The <expires> tag defines the caching time, and the <shared> tag specifies whether the cached page is shared by all users. Then, WebSphere Portal caches the HTML content generated by the portlet for the time defined in the <expires> tag. In that time period, the portlet always returns the same HTML content.

This is a helpful feature, but there are some scenarios in which this form of caching just won’t work.

  • Suppose you only want to cache part of the data. For example, you have a My investment portlet which displays a user’s stocks and mutual funds. Although mutual funds data is only updated once a day and can be cached, the stocks data keeps on changing. If you used the mechanism above, the portlet would always return the same content during the cache time, and the content would only be updated whenever the cache data expires. Therefore, the stocks data would not always be correct.
  • Suppose you want a portlet to display content based on a user action. For example, you have a Hot deals portlet that displays the hot deal selected by a user. The process to retrieve a hot deal is expensive; therefore, you want to cache the data, and so you try the mechanism above. The user selects a hot deal, and the content is cached by the portlet. Then, still during the cache time, the user selects a different hot deal. However, the portlet displays the content for the previous selected hot deal, because it has been cached and has not yet expired.

WebSphere Application Server V5 introduced a new built-in feature called the command cache which you can use to cache objects. For more information, see Using the command cache to improve portal application performance.

The command cache is a container-managed cache; EPPS is a bean-managed cache. In the referenced article, you see a sample of caching location information based on zip code. Suppose you are developing a portal application for the Texas government, and this application uses Texas location information more frequently than information about other states to improve performance. If you used command cache, all the data is cached for the same time defined in the xml configuration file. With the EPPS, you can define a default cache time and specific cache times for individual objects, to meet caching requirements based on business logic. You could cache the Texas location information for a different time than other data. Also, if you put the cache time data into a database, you can then change the cache time at run time.

You can use the EPPS in applications that run in either WebSphere Portal V4 or WebSphere Portal V5.

Therefore, you see that the EPPS adds additional flexibility to the caching mechanisms provided by WebSphere. Because EPPS is a portlet service, it is a discoverable extension to the portal functionality. A portlet can query the container for a specific service, and use that service without knowing the implementation or concerning itself with life cycle management. By implementing this caching enhancement (EPPS) as a portlet service, all portal applications can use it, and accross all portlets can share the cached data.


About the sample scenario

This article includes a sample application to illustrate when to use the EPPS, how to implement it, and how to deploy it.

Suppose you are developing a WebSphere Portal application for a financial services company, and you need to call a Web service provided by a partner company to retrieve mutual fund data. This retrieval is an expensive process. There are lots of mutual funds and the data is normally updated once a day. In this scenario, you see how to use the EPPS to cache the mutual funds data to improve the performance of your application.

The following products were used to develop and test the sample application:

  • IBM WebSphere Portal V4.2.1 and V5.0.2
  • IBM WebSphere Studio Application Developer v5.1
  • IBM Portal Toolkit, Version 5.0.2 for Multiplatforms
  • Microsoft® Internet Explorer V6.0
  • Netscape V7.1

To follow on with the description, download the sample application code, which includes the EPPS code.


Examining the EPPS

Figure 1 shows the state diagram for the EPPS Service.

Figure 1. State diagram of EPPS Service
State diagram of EPPS Service

To retrieve a property, the application calls the EPPS to check whether the property is cached. If the property is found and still valid, it returns the property. If the property is not found, or is expired, the application has to call the backend to get the property, save it to EPPS, and then return the property. Figure 2 shows the class diagram of the sample implementation of EPPS Service.

Figure 2. Class diagram of EPPS Service
Class diagram of EPPS Service

The sample implementation of EPPS Service is included in EPPSPortletService.jar, which is in the download.

Next, examine the EPPS classes.

IExpirablePropertiesService is an interface which defines the methods of EPPS, and it extends PortletService interface. All portlet services are required to implement the PortletService interface.

Listing 2. IExpirablePropertiesService interface
public interface IExpirablePropertiesService extends PortletService
{
  void saveProperty(Object propertyName, Object oneProperty);
  Object retrieveProperty(Object propertyName);
  boolean checkValidation(long birthTime, long lifeTime);
}

SavedProperty represents the object that is cached. Every property has lifeTime and birthTime attributes. The birthTime is the time when the property is obtained, and the lifeTime is specified in ObjectLifeTime.properties file.

Listing 3. SavedProperty class
public class SavedProperty {
  private long birthTime;
  private Object oneProperty = null;

  public SavedProperty(Object theProperty, long theBirthTime)
  {
    birthTime = theBirthTime;
    oneProperty = theProperty;
  }
	
  public long getBirthTime() {
    return birthTime;
  }

  public Object getOneProperty() {
    return oneProperty;
  }

  public void setBirthTime(long l) {
    birthTime = l;
  }

  public void setOneProperty(Object object) {
    oneProperty = object;
  }
}

ExpirablePropertiesServiceImpl class implements EPPS. To save a property, it creates a SavedProperty object, which contains the property and birthTime, and then it saves the created object into contentCache. To retrieve a property, it checks property validation. The following code shows the retrieveProperty method.

Listing 4. ExpirablePropertiesServiceImpl class
public Object retrieveProperty(Object propertyName) 
{	
  long lifeTime = 0;
  String lifeTimeString = null;
  Object savedProperty = null;
		
  if(contentCache != null)
  {
    savedProperty = contentCache.get(propertyName);
  } 
  if(savedProperty == null) // not found in cache
  {
    return null;
  }
  try // found in cache, check whether it’s valid
  {
  // retrieve life time from the property file
  lifeTimeString =ObjectLifeTime.getString((String)propertyName);
  }
  catch(Exception e)
  {
  System.out.println("Error " + e);
  }
	
  if(lifeTimeString == null || "".equals(lifeTimeString))  		{
  // if time not found in property file, pick up the default // life time
	lifeTime = defaultLifeTime; 
     }
     else
     {	lifeTime = Long.parseLong(lifeTimeString);	
     }

     if( checkValidation( 
      ((SavedProperty)savedProperty).getBirthTime(), lifeTime ))
     {
	//if valid,return the property
	return ((SavedProperty)savedProperty).getOneProperty();
     }
     else
     {
	//if not valid, remove the property
	contentCache.remove(propertyName);
     }
  return null;
}

ExpirablePropertiesHandler is used to connect the portlet service to retrieve or save properties.

Listing 5. ExpirablePropertiesHandler class
public class ExpirablePropertiesHandler 
{
  // retrieve the portlet service
  public static IExpirablePropertiesService 
     getExpirablePropertiesService(PortletContext portletContext)
    throws PortletException
  {
    IExpirablePropertiesService portletService = null;
      try
        {if(portletContext != null)	
	{
	  portletService=(IExpirablePropertiesService)portletContext.getService(
       IExpirablePropertiesService.class);
	}
	}
      catch(PortletServiceNotFoundException e)
	{
	  throw new PortletException(e.toString());
	}
	return portletService;
   }
	
/**
 * Retrieve a property from portlet service
 */
public static Object retrieveProperty(IExpirablePropertiesService 
  portletService, String propertyName)
 {
   if(portletService == null)
   {	return null;
   }
   return portletService.retrieveProperty(propertyName);
  }
	
/**
 * Save a property into portlet service
 */
public static void saveProperty(IExpirablePropertiesService 
  portletService, String propertyName, Object propertyValue)
 {
   if(portletService == null)
  {
    return;
  }
    portletService.saveProperty(propertyName, propertyValue);
  }
 }

ObjectLifeTime.properties is a property file which you use to specify the life time properties. The following code shows a sample of ObjectLifeTime.properties, which is also in the download. If the a property lifeTime is not defined in this file, EPPS uses the default_lifetime for that property. You could also use an XML file or a database table to contain the life times for your properties.

Listing 6. ObjectLifeTime.properties
# default life time is 2 hours (7200 seconds)
default_lifetime = 7200
# mutual funds life time is 12 hours (43200 seconds)
mutualFundsMap = 43200

The example uses PortletServiceCacheFactory as the factory class for the service. This class is a generic factory class shipped with WebSphere Portal and always returns the same instance of a given service.


Deploying the EPPS

Although the sample code for EPPS is the same for both WebSphere Portal V4.2.1 and WebSphere Portal V5.0.2, the deployment process is different.

To deploy the EPPS portlet service on WebSphere Portal V5.0.2:

  1. Copy EPPSPortletService.jar into ${wps_home}/shares/app directory, where ${wps_home} is the WebSphere Portal installation directory.
  2. Open ${wps_home}/shared/app/config/services/PortletServiceRegistryService.properties, and append the following lines to the end of the file.
    # The portlet service for caching data (ExpirablePropertiesService)
    servers.enable.isv.portletservices.expirableproperties.IExpirablePropertiesService = 
      servers.enable.isv.portletservices.expirableproperties.ExpirablePropertiesServiceImpl 
    servers.enable.isv.portletservices.expirableproperties.
                         ExpirablePropertiesServiceImpl.factory = 
      com.ibm.wps.pe.pc.legacy.service.PortletServiceCacheFactory
  3. Restart WebSphere Portal server.

To deploy the portlet service on WebSphere Portal v4.2.1:

  1. Copy EPPSPortletService.jar into directory ${was_home}/lib/app, where ${was_home} is the WebSphere installation directory. The default value on Windows platform is C:/WebSphere/AppServer.
  2. Open file ${was_home}/lib/app/config/services/PortletServiceRegistryService.properties, append the following lines to the end of the file.
    # The portlet service for caching data (ExpirablePropertiesService)
    servers.enable.isv.portletservices.expirableproperties.IExpirablePropertiesService = 
       servers.enable.isv.portletservices.expirableproperties.ExpirablePropertiesServiceImpl 
    servers.enable.isv.portletservices.expirableproperties.
                ExpirablePropertiesServiceImpl.factory = 
       org.apache.jetspeed.portletcontainer.service.PortletServiceCacheFactory
  3. Restart the portal server.

Examining the sample application

Next look at the sample portal application that uses the EPPS. As described in About the sample scenario, the application is a portal application for a financial services company. It includes two portlets:

My investment
which displays user-selected mutual funds and a stock list
Search mutual funds
which lets the user search mutual funds

The mutual funds data comes from a Web service provided by a partner company. Because the data is large and is only updated once per day, you can improve the performance of the portal application by using the EPPS.

This listing shows the data retrieval code.

Listing 7. Data retrieval code
public static HashMap retrieveMutualFundsMap(PortletContext context)
throws PortletException
{
HashMap allFunds = null;
try
{
 // Retrieve from portlet service
   IExpirablePropertiesService portletService=
                                   (IExpirablePropertiesService)context.getService(
       IExpirablePropertiesService.class);
   allFunds = (HashMap)ExpirablePropertiesHandler.retrieveProperty(
     portletService, "mutualFundsMap");
			
     // Not found in portlet service. Call Web service to get it.
     if(allFunds == null)
     {							
	MutualFundHandlerProxy proxy = new utualFundHandlerProxy();
		
	OneMutualFund[] fundArray = proxy.retrieveAllFunds();
	// Create a HashMap of mutual funds. 
	if(fundArray != null && fundArray.length > 0)
	{
	   allFunds = new HashMap(fundArray.length * 2);
	   for(int i=0; i < fundArray.length; i++)
	   {
	     allFunds.put(fundArray[i].getSymbol(), fundArray[i]);
	   }
	}	
      // save data to EPPS
       ExpirablePropertiesHandler.saveProperty(portletService, 
       "mutualFundsMap", allFunds);
     }	
}
catch(Exception e)
{
  throw new PortletException(e);
}		
 return allFunds;
}

As shown in the code above, after the data is retrieved from the Web service, the data is converted from an array to a hashmap, and then cached into EPPS. The cached data is shared by the two portlets.

Figure 3 shows the My investment portlet, whose mutual funds data is cached in EPPS. In this sample, the available mutual funds symbols are fund1, fund2, …, fund99.

Figure 3. My investment portlet
My investment portlet

Figure 4 shows the Search mutual funds portlet, which also uses the cached mutual funds data. That is, both portlets use the same cached data.

Figure 4. Search mutual funds portlet
Search mutual funds portlet

Deploying the sample application

See the download for the complete sample application and EPPS code.

To deploy sample code on WebSphere Portal v5.0.2:

  1. Install EPPS Service as described before.
  2. Deploy WebServiceEAR_v502 on the default server; this is the Web service application.
  3. Test the Web service using the following url: http://localhost:9080/MutualFundsWebServiceClient/sample/ MutualFundHandler/TestClient.jsp.
  4. Place EPPSWebServClt5.jar, webservce-runtime.jar, and xsd.bean.runtime.jar in the ${wps_home}/share/app directory.
  5. Add the three JAR files to the application server's WPSLib shared library.
  6. Install mutual funds portlets; the war file is MutualFundsPortlets_v502, and includes the Search mutual fund and Mutual funds list portlets.
  7. Put the two portlets on a page.
  8. Restart the WebSphere Portal server, and test the portlets.

To deploy sample code on WebSphere Portal v4.2.1:

  1. Install EPPS Service.
  2. Deploy and test the Web service application WebServiceEAR_v421 on the default server.
  3. Place EPPSWebServClt4.jar, MutualFunds.jar, webservice-runtime.jar, and xsd.bean.runtime.jar in the ${was_home}/lib/app directory.
  4. Install mutual funds portlets in war file MutualFundsPortlets_v421.
  5. Put the two portlets on a page.
  6. Restart the WebSphere Application Server and WebSphere Portal servers, and test the portlets.

Conclusion

The expirable properties portlet service (EPPS) illustrates a caching system that you can use in your WebSphere Portal applications to improve the performance. You can define the caching time for different data, based on business logic. The cached data is shared by all portlets. You could make the EPPS "dynamic" by placing the properties data in either an XML file or database. Using this type of portlet service gives you additional, flexible portlet caching options.


Download

DescriptionNameSize
examples for expirable properties portlet serviceepps_code.zip  ( HTTP | FTP )210 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=23604
ArticleTitle=Improving the performance of WebSphere Portal applications using the expirable properties portlet service
publish-date=10062004