IBM WebSphere Developer Technical Journal: Using the command cache to improve portal application performance

Caching can improve the performance of your application more than any other technique in your coding arsenal. This article illustrates how to use one of the advanced caching features in WebSphere® Application Server V5, the command cache, to improve portal application performance.

Joey Bernal (abernal@us.ibm.com), Portal Architect, IBM Software Services for WebSphere

Anthony (Joey) Bernal is a Portal Architect with IBM Software Services for Websphere. Working with WebSphere Portal since the initial release 1.1, he has an extensive background in the design and development of portal applications and has led the implementation of many projects using IBM's WebSphere Portal. Joey is an accomplished author, speaker and instructor in various topics concerning WebSphere Portal and related technologies.


developerWorks Professional author
        level

Varaprasad Bhatta (vbhatta@us.ibm.com), WebSphere Consultant, IBM Software Services for WebSphere

Varaprasad (Prasad) Bhatta is a Senior IT Specialist at IBM Software Services in NE area. He primarily works on portal architecture and implementation.



04 August 2004

Introduction

Get the products and tools used in this article

If you are a developerWorks subscriber, you have a single user license to use WebSphere Application Server, WebSphere Portal, WebSphere Studio Application Developer, and other DB2®, Lotus®, Rational®, Tivoli®, and WebSphere products -- including the Eclipse-based WebSphere Studio IDE -- to develop, test, evaluate, and demonstrate your applications. If you are not a subscriber, you can subscribe today.

Caching support in WebSphere Application Server V5 includes includes servlet and JSP™ results caching -- the same HTML fragment caching released in V4, except that V5 significantly extends the product's caching ability. For example, you can now include other objects for different caching needs. This article focuses on the command caching portion of this functionality.

Using command caching is an advanced topic. This article assumes some basic level of caching knowledge and a solid understanding of portal development. Portal developers should be familiar with WebSphere Studio, Web services and portlet services. See Resources for references to other articles that can help you gain a basic understanding of caching functionality available within WebSphere. While this article is aimed at portal developers who need to incorporate some caching into their portlet applications, WebSphere developers in general may benefit from the specific code examples provided for the use of the command cache.

Our caching example

The example code available for download with this article will enable you to install and test a working sample. The example was built and tested using the following software and hardware:

  • Windows NT®/2000/XP machine with 1G RAM
  • WebSphere Studio Application Developer Version 5.1
  • WebSphere Application Server V5.0.2
  • WebSphere Portal V5.0.2

You will also need a working internet connection from your machine to connect to the sample ZipCode Web service.

During the design of an application, you can often identify many opportunities for caching fragments of data within the different layers. How you choose to handle caching is often based on the type of data that you are caching and how that data is used. Generic HTML snippets or fragments can be cached as HTML fragments that are output from a servlet or JSP. More complex data types, or content not used directly within the presentation layer but instead are used to determine what is displayed to a user, may need to be cached as an object or bean containing some discrete set of data.

Figure 1 shows the example used in this article. Many portlets need to call a third-party service such as a Web service or other legacy system. In this example, you see how to create a portlet service which wraps a Web service and which uses caching. The data for this portlet is provided by a simple Web service available from the Xmethods Web site.

Figure 1. Portlet service with command cache
Figure 1. Portlet service with command cache

Specifically, the method used in this example is the ZiptoLatLong() method. Given a specific zipcode, ZiptoLatLong() returns a set of data that includes location coordinates and other location data.

This example is somewhat contrived in that it simply displays the cached data as-is, using a portlet. In many cases, this approach would be better handled using servlet cache to hold the HTML fragments that can be identified by unique keys. The real power of the command cache is when caching data that is not used in an very apparent way to the user, but rather the cached attributes or data are calculated and the results are displayed on the page. However, while the example is simple, it is designed to demonstrate the overall approach for using command cache with a portal application.

Other caching scenarios

In the example, we chose to cache the results of a Web service call, but there are many types of data that can be cached and different reasons to use the command cache. For example, you could store user profile or user session data, rather than using the HTTPSession to store the data. Other examples include storing custom data from a source other than a Web service, and storing connections to various resources for reuse among various applications or portlets. This type of caching can greatly reduce the number of calls to back end resources, resulting in improved performance and greater scalability of your application.

Dynamic caching and the key

The dynamic cache service works by intercepting calls to cachable objects within the application server. Previously published articles (see Resources) show how to intercept a call to a servlet or portlet and cache the servlet output as an HTML fragment. WebSphere can also intercept a call to the execute() method of a command object and store the content of the object within the dynamic cache. Dynamic caching can also cache additional data types, such as Web services and patterns; those topics will be left for a later article.

As with servlet caching, command caching requires a unique cache ID as the key for storing and retrieving something from the cache. A key can be anything unique and based on methods and fields within your cachable object. For example, the key could be a unique user ID, a stock symbol or, in our case, a zip (postal) code.

Cachespec.xml

The ability to cache command objects within WebSphere Application Server is configured using cachespec.xml. In earlier versions of WebSphere Application Server, configuration was performed using the servletcache.xml file. This file is still supported; however, cachespec.xml is the preferred and future approach. When you deploy the service, place the cachespec.xml in this directory:

<websphere-home>/AppServer/installedApps/<myserver>/wps.ear/wps.war/WEB-INF

The cachespec.xml (in the ZiptoLocService.jar in the download) is shown in Listing 1.

Listing 1. The cachespec.xml configuration file

<?xml version="1.0"?>
<!DOCTYPE cache SYSTEM "cachespec.dtd">
<cache>
   <cache-entry>
      <class>command</class>
      <sharing-policy>shared</sharing-policy>
      <name>com.ibm.portletservice.zipservice.ZipCacheCommand</name>
      <cache-id>
         <component type="method" id="getZip">
            <required>true</required>
         </component>
         <priority>1</priority>
         <timeout>180</timeout>
      </cache-id>
   </cache-entry>
</cache>

The WebSphere dynamic cache parses the XML file when the application is loaded within the application server. The parameters used determine the names and type of objects that are cached. There are many parameters and configuration options available for the cachespec.xml file. (See the WebSphere Application Server Information Center in Resources.) For example, you could have multiple occurrences of the <component></component> tag based on the CacheCommand constructor for your service.

Creating the example

The steps to building the example are:

  1. Create a basic Web services client
  2. Define the portlet service interface
  3. Cache the Web service result
  4. Implement the portlet service
  5. Deploy the completed service
  6. Test with the sample portlet.

The remainder of this article guides you through these steps.


1. Create a basic Web services client

You can easily create a Web service client using WebSphere Studio Application Developer (hereafter referred to as Application Developer). Using the Web Services Client wizard in Application Developer to do the work provides several advantages. It:

  • Creates all the client code, stubs, and proxies needed to communicate with the Web service.
  • Performs the necessary Java™-to-XML translation very efficiently, reducing the need for manual coding and, potentially, coding mistakes.
  • Provides the input and output beans and methods for calling and using the Web service quickly and easily.

Create a project for the service

Before you create the Web service client, you need to create a project in which you can create and test it. The Web service client will eventually become the portlet service:

  1. In Application Developer, create a Dynamic Web Project using the WebSphere Studio wizards.
    Figure 2. Create a dynamic Web project
    Figure 2. Create a dynamic Web project
  2. Name the project ZipService and create an EAR project named ZipServiceEAR.

Create the client

To create the Web service client:

  1. In Application Developer, choose File => Web Service Client (Figure 3).
    Figure 3. Create Web service client
    Figure 3. Create Web service client
  2. On the Web services form, select Java proxy for Client proxy type, and check Test the generated proxy. Allow the wizard to Create folders when necessary to contain the generated code. After choosing these options, select Next (Figure 4).
    Figure 4. Web services form
    Figure 4. Web services form
  3. Because this is the first step in building a complete service, we will want to leverage the WebSphere Test Environment to test our client when it is created. For Client Web Project, select ZipService, which was created earlier to hold the client code, then select Next (Figure 5).
    Figure 5. Client Environment Configuration
    Figure 5. Client Environment Configuration
  4. On the Web services Selection Page (Figure 6), enter the WSDL location that is provided for the service selected. For this example, enter the WSDL file location as: http://www.winisp.net/cheeso/zips/ZipService.asmx?WSDL. Select Next.
    Figure 6. Web Service Selection
    Figure 6. Web Service Selection
  5. On the Web Service Proxy Page (Figure 7), choose to Generate proxy for the client. Leave the security configuration to No Security and leave Define custom mapping for namespace to package unchecked. Select Next.
    Figure 7. Web Service Proxy Page
    Figure 7. Web Service Proxy Page
  6. On the Web Service Client Test form (Figure 8), select Test the generated proxy. In an effort to simplify the generated code, uncheck all the methods that are available within the service, except for the service method that we will be actually using. (If you leave all the methods checked, there is more generated code. Therefore, uncheck the methods so it is easier to examine only the necessary generated code to understand how it works.)
  7. To run the client on the embedded test server, select Run test on server, then Finish.
    Figure 8. Web Service Client Test
    Figure 8. Web Service Client Test

Test the client

After Application Developer generates the client code, it publishes and runs your code within the WebSphere Studio embedded test client. You can then test the generated client code and ensure that everything is working as required.

Figure 9. Testing client on server
Figure 9. Testing client on server

At this point, you have generated the Web service client. Next, you will wrap it within the portlet service and implement caching.

If you are not already familiar with the code, this is a good time to examine the code to see what was generated for the Web service client. A good place to start is with the generated test client JSP files. Starting with the Results JSP that is generated with the client, you will see that the test code would invoke and display the Web service results. When you understanding how Web services client code is generated by WebSphere Studio, you will find that this will help with other projects that require building Web services and client code.


2. Define the portlet service interface

Portlet services are components in WebSphere Portal which enable you to share common functionality across an entire portal. Portlets, and in many cases other objects (such as a portal theme), can lookup and instantiate a service through dynamic discovery. WebSphere Portal provides several service factories (or you can build your own) for use in creating or locating a portlet service instance.

Generally, we prefer using portlet services over more traditional objects, such as singletons, because:

  • The use of portlet services can provide a documented and enforceable standard across your development team.
  • Portlet services are a supportable way to separate layers of concern across your application and to encapsulate common logic.
  • Portlet services are easy to implement and enable inexperienced developers to provide their own service components.

While a portlet service is not the best choice for every shared component requirement, in many cases it can serve as an excellent starting point for your application. (See Resources for more information.)

The service interface for our example is very simple, consisting of one method that can be called by the sample portlet to retrieve the location information, based on a zip code.

Listing 2. ZipService interface

package com.ibm.portletservice.zipservice;

import org.apache.jetspeed.portlet.service.*;
import org.dyndns.dinoch.*;

public interface ZipService extends PortletService {
	public org.dyndns.dinoch.LatLong ZiptoLatLong(String zip);
}

To enable a portlet service, extend the PortletService interface, and then implement the required methods and business logic methods. After you have created and implemented the service interface, you can register it with WebSphere Portal by adding a few lines to the PortletServiceRegistryService.properties file within the portal. (See Deploy the completed service for more about this file.


3. Cache the Web service result

To implement the caching part of our service, extend the cachableCommandImpl class. This abstract class implements the cachableCommand interface. It provides implementations for some of the methods and declares additional methods that your class must implement.

Listing 3. Extending the cachableCommandImpl class

package com.ibm.portletservice.zipservice;

import com.ibm.websphere.command.cachableCommandImpl;
import org.dyndns.dinoch.*;

public class ZipCacheCommand extends cachableCommandImpl {

   private String zip = null;
   private org.dyndns.dinoch.LatLong latLongBean = null;

   public ZipCacheCommand(){}

The command is initialized with whatever you define as your unique key (in this case, a zip code), enabling the command to determine whether to call the execute() method. The isReadyTo-CallExecute() method ensures that this zip code has been set within the command.

Listing 4. Initializing the command

public ZipCacheCommand(String zip){
   this();
   this.zip = zip;
}

public boolean isReadyToCallExecute() {
   return zip != null;
}

The performExecute() method calls our Web service and stores the results in a latLongBean bean, which is returned to a calling method using getLatLong().

Listing 5. The performExecute() method

  public void performExecute() throws Exception {

      org.dyndns.dinoch.LatLong zipToLatLong = null; 

      try {

         System.out.println("performExecute zip = " + this.zip);
         ZipcodeLookupServiceSoapProxy proxy = 
            new ZipcodeLookupServiceSoapProxy();	
         latLongBean = proxy.zipToLatLong(this.zip);

      } 
         catch (Exception ex){
         System.out.println("Exception in performExecute()");
         ex.printStackTrace(System.out);
      }
   }

   public String getZip() {
      return zip;
   }

   public org.dyndns.dinoch.LatLong getLatLong() {
      return latLongBean;
   }

}

4. Implement the portlet service

With most of the underlying code in place for completing the service, you are ready to implement the portlet service interface that was defined earlier. You will then install the complete service into WebSphere Portal.

The basic headers of the service implementatation define the class and import the required libraries for proper execution. The PortletServiceProvider interface requires you to implement two methods in your class: the init() and destroy() methods. You can use the init() method to read parameters from the PortletServiceRegistryService.properties file, and to initialize any required settings.

Listing 6. Implementing the required methods

package com.ibm.portletservice.zipservice;

import org.apache.jetspeed.portlet.service.*;
import org.apache.jetspeed.portlet.service.spi.*;
import javax.servlet.ServletConfig;
import org.apache.jetspeed.portlet.PortletRequest;
import java.io.*;
import com.ibm.websphere.command.CommandException;
import org.dyndns.dinoch.*;

public class ZipServiceImpl implements ZipService,PortletServiceProvider {

	public void init(PortletServiceConfig config) {
	// intialize the service
	}

	public void destroy() {
	}

In a real world development effort, you might externalize the location of the Web service to a property setting so that you could use different versions of a Web service. For example, a Q/A portal could point to its Q/A version of the Web service, and the production portal could point to the production version of the Web service. In the case of our example, the Web service is external to our organization and that is not an option. However, you can see how storing the location in a property could be useful.

The next part implements the ZiptoLatLong() method defined in our portlet service interface. This service ends up being pretty simple because we have encapsulated all the other components into their required functionality.

Listing 7. Implementing ZiptoLatLong()

public org.dyndns.dinoch.LatLong ZiptoLatLong(String zip) {
		
	org.dyndns.dinoch.LatLong zipToLatLongmtemp = null; 
	ZipCacheCommand cache = new ZipCacheCommand(zip);

	try {	
	      cache.execute();
	} catch (Exception ex) {
	      ex.printStackTrace(); //always do something!
	} 
	
	return cache.getLatLong();  //null if client failed.
   }
}

The input into the service is a zip code as a type String. Then, the method:

  1. Creates a new instance of a LatLong bean called zipToLatLongmtemp to hold the return data from the Web service.
  2. Creates and initializes a ZipCacheCommand bean with the zip code.
  3. Calls the execute() method on the command object, which returns a cached LatLong or a new result from the Web service.

Figure 10 shows how these objects come together to fully implement the service that we are creating.

Figure 10. Zip service class diagram
Figure 10. Zip service class diagram

That's it! It really is much easier than it appears, because you can use WebSphere Studio to create the Web service client code, and WebSphere Application Server to take care of all the caching logic behind the scenes. The hardest thing you have to do is decide on a proper key!


5. Deploy the completed service

Once you have compiled your code into class files, you package it into a JAR file for deployment into your portal. To install the service:

  1. Install the class files in the <websphere-home>/PortalServer/shared/app directory. You can place either the JAR file or the actual package folders and class files into this directory.
  2. Update the PortletServicesRegistryService.properties file to include the portlet service.
  3. Place cachespec.xml into: <websphere-home>/AppServer/installedApps/<myserver>/wps.ear/wps.war/WEB-INF.

Final JAR file structure

For a complete understanding of the files included in the JAR file, let us look at its structure:

Listing 8. ZiptoLocService.jar contents

+ com
  + ibm
     + portletservice
        + zipservice
            ZipCacheCommand.class             - cachable Command Ojbect
            ZipService.class                  - Portlet service Interface
            ZipServiceImpl.class              - Portlet service Implementation
+ org
  + dyndns
    + dinoch
        LatLong.class                         - Results bean from Web service
        ZipcodeLookupServiceSoapProxy.class   - Used to call the Web service
	...  additional Web service client classes

You need to include the additional files under the org.dyndns.dinoch package in the JAR file, which are not shown here for simplicity. (See ZiptoLocService.jar in the download file.)

Updating the properties file

Using portlet services requires that you register the service with the portal server by mapping the service and implementation class, and associating the service with a factory.

To register the service:

  1. Edit the PortletServiceRegistryService.properties file located in <WAS_HOME>\PortalServer\shared\app\config\services, as shown in Listing 9.

    Listing 9. Registering the service in PortletServiceRegistryService.properties

     @copyright properties
    
    # ---------------------------------- #
    # Properties of the PortletServiceRegistry Service #
    # ---------------------------------- #
    
    org.apache.jetspeed.portlet.service.default.factory = 
         com.ibm.wps.pe.pc.legacy.service.PortletServiceDefaultFactory
    
    
    com.ibm.portletservice.zipservice.ZipService = 
         com.ibm.portletservice.zipservice.ZipServiceImpl
    com.ibm.portletservice.zipservice.ZipServiceImpl.factory = 
         com.ibm.wps.pe.pc.legacy.service.PortletServiceCacheFactory
    
    
    org.apache.jetspeed.portlet.service.ContentAccessService = 
          com.ibm.wps.pe.pc.legacy.service.ContentAccessServiceImpl
    
    ...

    In this example, the ZipService is mapped to the PortletServiceCacheFactory, which will cache in-stances of this service and serve them to the portlets as required.
  2. If there were startup parameters for this service, you would make them available to the service here, as well.
  3. Restart the portal server so the above changes take effect.

6. Test with the sample portlet

The portlet used for this example provides a simple way to test the service and ensure that the results are being cached correctly. It consists of a simple controller and two JSP files. The JSP files make up the presentation layer components; they are included in the download file. The first JSP provides an interface for the user to enter the zip code, and then retrieves the results of the Web service call.

Figure 11. Portlet with lookup JSP
Figure 11. Portlet with lookup JSP

The only class file in the portlet is the portlet controller class, called ZiptoLocPortlet. To keep things simple, the only method we will discuss is the doView() method. The need for an actionPer-formed() method was removed by handling the action in the doView().

The controller defines two parameters along with the import statements. These static values represent the JSP files that are displayed by the portlet, based on user interaction.

Listing 10. ZiptoLocPortlet

package com.ibm.portlet.ziptoloc;

import java.io.IOException;

import org.apache.jetspeed.portlet.PortletAdapter;
import org.apache.jetspeed.portlet.PortletConfig;
import org.apache.jetspeed.portlet.PortletContext;
import org.apache.jetspeed.portlet.PortletException;
import org.apache.jetspeed.portlet.PortletRequest;
import org.apache.jetspeed.portlet.PortletResponse;
import org.apache.jetspeed.portlet.UnavailableException;

import com.ibm.portletservice.zipservice.ZipService;

public class ZiptoLocPortlet extends PortletAdapter {

   public static final String VIEW_JSP     = "/jsp/ZiptoLocView.";
   public static final String RESULT_JSP   = "/jsp/ZiptoLocResult.";

   public void init(PortletConfig portletConfig) throws UnavailableException {
      super.init(portletConfig);
   }

The doView() method implements the main work for the example portlet. It looks for a zip code parameter in the portlet request. If the user has entered a zipcode in the view JSP file and clicked submit, then this value will be available.

Listing 11. ZiptoLocPortlet

#   public void doView(PortletRequest request, PortletResponse response) 
         throws PortletException, IOException {

      String zip = request.getParameter("zip");

If the request parameter is not available, then the portlet simply displays the view JSP.

Listing 12. Testing for a null zip code

      if (zip == null || zip == "") {
	
         getPortletConfig().getContext().include(VIEW_JSP + 
            getJspExtension(request), request, response);

If the parameter is available, then the portlet gets a handle to the portlet service and calls the service.ZiptolatLong(zip) method. That method places the result in the request object and displays the results JSP.

Listing 13. Handling a zip code

      } else {
			
         PortletContext context = this.getPortletConfig().getContext();
         ZipService service = 
            (ZipService)context.getService(ZipService.class);		
         org.dyndns.dinoch.LatLong result = 
            service.ZiptoLatLong(zip);
         request.setAttribute("latLong", result);
	
         getPortletConfig().getContext().include(RESULT_JSP +
            getJspExtension(request), request, response);
      }
   }
}

The result JSP file iterates through the elements in the LatLongBean and displays them in the portlet window.

Figure 12. Test portlet with the results JSP
Figure 12. Test portlet with the results JSP

As stated earlier, this simple example is not necessarily a real world one. If the data were to be displayed in this fashion, the servlet cache or portlet cache from a Web services portlet would probably be a better approach.

Using the cache monitor

You can use the cache monitor to provide a view into the Dynamic Cache. The monitor shows basic statistics, such as the number of entries in the cache and the number of hits and misses for cache requests. You can view these statistics to help determine how your cache is performing, and whether the size of your cache is appropriate.

Preparing to use the monitor

The next section takes you through the steps of installing the cache monitor application. The application should be installed on the server that needs to be monitored. The application EAR file is located in the <websphere-home>/AppServer/installableApps directory. You must install this component in the server whose cache contents you want to view; for example, in a typical installation, the WebSphere Portal server and not server1. Also, make sure you choose admin_host instead of default_host during the installation process. This will prevent anyone accessing the cache monitor on the default_host port.

After an object is cached, you can view it in the Cache Contents section of the monitor. The entries on this page include the object that is cached, based on the template that was defined in your cachespec.xml file. You will also see the cache ID of the entry, priority, timeout, and of other information.

For servlets that are cached, you can select an entry and see the actual HTML fragment that was cached for the servlet output.

Installing the cache monitor

To install the DynaCacheMonitor Web application in the WebSphere Portal server:

  1. Make sure server1 is started.
  2. Log into the admin console using http://localhost.domain.com:9090/admin. If security is enabled as a default portal, logon as wpsbind/wpsbind; otherwise, logon as administrator.
  3. Select Applications => Install New Application.
  4. On the Step 1 page, click the Browse button and choose the file C:\WebSphere\AppServer\installableApps\CacheMonitor.ear, and then Next.
  5. On the Step 2 page, check Dynamic Cache Monitor, select admin_host as the Virtual Host, and then select Next.
    Figure 13. Install cache monitor, Step 2
    Figure 13. Install cache monitor, Step 2
  6. On the Step 3 page, select &server=WebSphere_Portal server from the Clusters and Server list, select Apply, and then Next.
    Figure 14. Install cache monitor, Step 3
    Figure 14. Install cache monitor, Step 3
  7. On the Step 4 page, select Administrator and All Authenticated users, and then Next.
    Figure 15. Install cache monitor, Step 4
    Figure 15. Install cache monitor, Step 4
  8. Select Next, then Finish.
  9. Be sure to add the admin port to the virtual host admin_host definition, if it is not already available.
  10. Save the Master Configuration file.
  11. Restart WebSphere Portal.

If you do not have security enabled, you can access the CacheMonitor console using:

http://hostname.domain.com:9091/cachemonitor

With security enabled, you can use:

https://hostname.domain.com:9044/cachemonitor/logon.jsp
Figure 15. Cache Monitor display
Figure 15. Cache Monitor display

Figure 15 shows how the same object can be cached multiple times with different cache IDs to determine the contents.

Using the test portlet to create cache entries

If your portlet and cache are working successfully, you should start to see entries in the cache monitor for each new zip code you enter that returns valid results. Viewing the results in the cache monitor is a good validation that you have done everything correctly and that your cache is working. You can also invalidate entries in the cache or change the settings in your cachespec.xml file to watch the cache refresh. Some basic timing print statements in your portlet service could be used to take the example even further and see the difference between a full Web service call and an entry that is pulled from the cache.


Conclusion

While the caching example described in this article can be very helpful in many situations, it does take some experience to know how these examples should be integrated into your application for the best performance improvements. We want to be very clear: caching does not always make up for bad design and coding practices; when you design and develop an application, you must consider performance and good coding practices for all aspects of the project lifecycle. Using a cache when it is not necessary, or trying to make up for a bad application design with caching, may give you some initial quick wins, but would not be the best solution in the long run.

This article is not all-encompassing regarding all necessary details. For example, after you build the Web service client using the wizard, you need to look through the generated code to determine which classes to use when you want to call the service. The generated test JSP files provide some clues. Look at the generated results.jsp to see exactly how the client should be instantiated and called.

Similarly, we did not address all administrative questions. For example, if you want to install the portlet service itself, and you plan to use a JAR file, the JAR must be registered within the classpath of the JVM. Administrative information can be found in the WebSphere Portal Information Center.

However, with a little experience you will find the answers will come quite easily as you design and develop more portal applications. Good luck and have fun!


Download

DescriptionNameSize
Code sampleziptoloc-cacheexample.zip  ( HTTP | FTP )39 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=13685
ArticleTitle=IBM WebSphere Developer Technical Journal: Using the command cache to improve portal application performance
publish-date=08042004