Skip to main content

skip to main content

developerWorks  >  WebSphere  >

IBM WebSphere Developer Technical Journal: Using filters to adapt existing portlets to new portal applications

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


New site feature

Check out our new article design and features. Tell us what you think.


Rate this page

Help us improve this content


Level: Intermediate

Shunguo Yan (shunguoy@us.ibm.com), Staff Software Engineer, IBM Software Group

14 Apr 2004

WebSphere portlet filter technology provides a quick solution for adapting and customizing existing portlets so that they may be used in new or different portal applications. A portlet filter is a Java module that can be dynamically plugged into one or more existing portlets to modify portlet request and response, as well as to add new functions to the existing portlets without requiring changes to them. This article describes WebSphere portlet filter basics, its differences from a servlet filter, and how to develop and use a portlet filter to adapt and customize existing portlets.

Introduction

Numerous portlets have been developed and delivered, ready for installation in WebSphere® Portal. Besides the internal portlets which are included with WebSphere Portal, many portlets have been developed by enterprise application vendors for providing accesses to their systems, and by individual developers for performing specific portal functions or providing solutions to specific problems. Hundreds of portlets are already available for use through the WebSphere Portal Catalog alone, covering a wide variety of applications and industries. Typically, a portal will use one or more existing portlets to provide certain functionality and to speed up development. In some cases, using an existing portlet is the only way to access a vendor-specific enterprise application from a portal due to security control or unexposed interfaces.

Although a portlet generally provides some customization through configuration, it is typically very limited. Additional customization is sometimes needed for existing portlets before they can be used in a portal, ranging from simple customization (such as, to provide a more consistent look with the rest of the portal) to more complex (such as, adding new functions). Consider an existing file upload portlet. There may be a need to plug in a custom algorithm to examine file content to be uploaded; if the file content is inappropriate, it should be rejected before it reaches the backend system. For an existing news channel portlet, which provides real time world news, only the news from specific regions or topics may be of interest and the rest should not be displayed. Frequently, portal-wide performance tuning may require that additional logic be added to each portlet in the portal to measure its execution time.

There is more than one way to adapt and customize an existing portlet. The most common way involves object-oriented inheritance, which enables you to derive a new portlet from an existing one to add new functions, as the core of a portlet is one or more Java classes. This approach suffers from major disadvantages:

  • First, a new portlet must be created from the existing one so that it may be customized.
  • Second, since a portlet application is delivered as a Web application archive (WAR) file, the new portlet cannot directly reference the classes in the WAR of the existing portlet; all the classes and their dependencies in the WAR must be unpacked and repacked into the WAR for the new portlet.
  • Additionally, care must be taken while invoking portlet methods (for instance, service and actionPerformed) which otherwise are invoked by the container only.

In contrast to inheritance-based customization, WebSphere portlet filter technology provides an easier and better approach for reusing and customizing existing portlets:

  • A portlet filter is a reusable Java class (or classes) that can be added or removed declaratively in a standard manner without requiring changes to the existing portlet or group of portlets which it modifies.
  • A filter is not a portlet; filters do not create a response to a request but, rather, intercept and modify the request before it is passed to the target portlet for processing, and the response before it is aggregated to the portal page.
  • A filter is not tied to any given portlet and therefore its lifecycle is not dependent on any individual portlet. This means that once the filter has been initialized, it can be applied to all applicable portlets dynamically with no further initialization cost.
  • In addition, since a filter is independent of any portlet, the WAR of the existing portlet or portlets is rarely needed to create a filter.

WebSphere transcoding and machine translation are based on portlet filter technology. A detailed description on WebSphere transcoding and translation can be found in the WebSphere Portal Information Center for Version 5.0 and the related article listed in the Resources section.

This article describes WebSphere portlet filter basics, differences between a portlet filter and a servlet filter, and how to develop and use a portlet filter to customize a portlet. In addition, various development issues are addressed to help ease its use. A filter called File Content Filter, which adds fine-grained file control mechanism to existing file upload portlets, is developed in this article as an example to demonstrate the use of a portlet filter.

You can find several file upload portlets available for WebSphere Portal. The Portal Document Manager (PDM) portlet and Portlet Installation portlet are installed by default in WebSphere Portal. Many more are listed in the WebSphere Portal Catalog. The PDM portlet is referred to in this article as an example to demonstrate the use of the File Content Filter. In WebSphere Portal V5, the PDM portlet is automatically installed in the Document page under My Portal by default. It provides a simple, real-time document viewing and contribution solution for portal users. PDM enables users with Editor role authority to upload almost all types of files. For many organizations, however, the requirements of this functionality may be far more complicated than the standard behavior provided by the PDM portlet. For example, a file control mechanism may be applied to control file types that can be uploaded, log the uploaded files and their properties, report upload success or failure status, etc. The File Content Filter developed in this article will modify the behavior of the PDM portlet so that only certain types of files are allowed to be uploaded.



Back to top


Portlet filter vs. servlet filter

If you are familiar with servlet filters (see Java Servlet Specification for details), you may have already noticed some similarities between a portlet filter and a servlet filter from what you have read so far. Indeed, they are similar in that both can be declaratively plugged in to intercept and modify a request and a response. However, it is important to understand that they are significantly different. To some extent, their differences are related to the differences between a servlet and a portlet: a servlet filter is a portal-level filter which is used to modify an entire portal page aggregated from several small pieces (responses from all the portlets in the page), while a portlet filter can be only applied to those small pieces. A servlet filter, if installed, is the first component that receives and modifies a client request and the last component that modifies the response to the client (see Figure 1).


Figure 1. A client request event sequence with both servlet and portlet filters
Figure 1. A client request event sequence with both servlet and portlet filters

As shown in Figure 1, a servlet request (step 1) is first processed through a chain of servlet filters (step 2) before it is dispatched into one or more portlet requests (step 3). A portlet request is further forwarded to a chain of portlet filters for processing (steps 4 and 5) before the result is aggregated (steps 6 and 7). The aggregated result is then passed back to the servlet filter for processing (step 8) before it is finally displayed to the user (step 9).

A filter chain contains one or more filters. After one filter finishes processing, the new request and response are passed to the next filter in the chain; the last filter in the chain invokes the target resources (servlet or portlet).

Like a servlet filter, a portlet filter is an optional component in WebSphere Portal architecture. Therefore, one, neither, or both types of filters can be used during real-world problem solving. For example, a servlet filter may be used to compress and encrypt an entire portal page, while a portlet filter may be more proper for compressing and encrypting only a portion of a portal page. In WebSphere Portal Transcoding Technology (see Resources), portlet-level transcoding uses portlet filters to do content transformation, markup conversion, annotation, etc., while portal-level transcoding uses servlet filter (or portal filter, as it is called in WebSphere Portal) to provide deck fragmentation.



Back to top


Portlet filter support and development

Portlet filter support classes are defined in the com.ibm.wps.pe.pc.legacy.cmpf package in WebSphere Portal. The PortletFilter interface provides three methods to manage the portlet lifecycle:

  1. void init(PortletFilterConfig config)
    Called once by the container to prepare the filter for service. The PortletFilterConfig object (config) allows the filter to access configuration parameters as well as a reference to portal context.
  2. void destroy()
    Called after the filter has been taken out of service. This method allows the filter to clean up any resources that are being held.
  3. void doFilter(PortletFilter.Method method, PortletRequest request, PortletResponse response, PortletFilterChain filterChain)
    Performs actual filtering work. This method allows the filter to inspect and modify the request and the response, or skip the processing of the request altogether. The first parameter (method) is the type of requested method that the filter can invoke (such as SERVICE or ACTIONEVENT). The last parameter (filterChain) contains a list of registered filters which still must be processed.

The PortletFilterAdapter class in the package provides a default implementation for the PortletFilter interface. The default implementation of the doFilter method is delegated to a set of do methods (doService, doTitle, doActionEvent, doMessageEvent, doLogin, doBeginPage and doEndPage) based on the type of requested method passed as the first parameter in the doFilter method. The default implementation of the do methods does nothing but pass the original request and response to the next filter in the chain or the target portlet. Each do method of a filter is invoked before the corresponding method on the target portlet is invoked. Table 1 lists mappings between each filter method and target portlet method.

Table 1. Portlet and portlet filter methods

Portlet Filter MethodsPortlet Methods
doServiceservice or its helper method (doEdit, doView, doConfigure or doHelp)
doActionEventactionPerformed
doMessageEventmessageReceived
doLoginlogin
doTitledoTitle
doBeginPagebeginPage
doEndPageendPage

A custom portlet filter should extend the PortletFilterAdapter class and override one or more of the do methods listed in Table 1. For example, if a custom filter supports only the portlet VIEW mode and modifies the output, then only the doService method needs to be overridden. However, if a filter supports portlet ActionEvent and modifies the output, then both the doService and doActionEvent methods should be overridden (see the following sections for details). WebSphere Portal provides three convenient wrapping classes:

  • PortletRequestWrapper for PortletRequest
  • PortletResponseWrapper for PortletResponse
  • ClientWrapper for client interface.

The wrapping classes should be used to create custom request, response and client classes so that new functionality can be added easily without having to implement the entire interface.


Figure 2. Request event sequence for a service request with a portlet filter
Figure 2. Request event sequence for a service request with a portlet filter

Typical filter development involves following steps, also shown in Figure 2, which shows the event flow of a service request with a portlet filter, as well as processing steps in a portlet filter:

  1. Initialize filter and retrieve configuration data
  2. Inspect and modify the portlet request
  3. Buffer the response stream
  4. Invoke or block the filter chain
  5. Modify the response stream
  6. Output the modified response stream using the original writer
  7. Post processing in a filter.

Some of these steps will, of course, be optional or not apply to all filters. For example, if a filter does not modify the request, then the steps involving request processing can be ignored.

The following sections will describe the steps in detail with the File Content Filter as an example.

Initialize filter and retrieve configuration data

Portlet configuration data are optional parameters set up in portlet configuration file PortletFilterService.properties, which is in the PORTAL_HOME\shared\app\config\services directory in WebSphere Portal, where PORTAL_HOME is the server installation directory. A configuration for the File Content Filter, named FileContentFilter, is shown in Listing 1 as an example. Listing 1 indicates that the File Content Filter will override the doActionEvent and doService methods and has a configuration parameter called Trace which indicates whether tracing for the filter should be on or off. (All trace statements are removed from all the code samples in this article to avoid the lengthy text. You can find a complete source code in the download file.)

Listing 1. File content filter configuration

# ------ File Content Filter ------ #
# filter name, required
filtername14 = FileContentFilter       
# filter implementation class, required
FileContentFilter.classname = myportlet.filters.FileContentFilter  
# supported methods, at least one is required
FileContentFilter.method.1 = ActionEvent  
FileContentFilter.method.2 = service
# configuration parameter, optional   
FileContentFilter.Trace = true   

The portlet filter retrieves configuration parameters in its init method by calling the getInitParameter or getInitParameterNames method on the PortletFilterConfig object, which is passed by the container to the init method as a parameter. A reference to the filter run time environment (portal context) is also available through calling getPortalContext (Listing 2). The portal context is a type of ServletContext which can be further used to access the system log, load resources from the container, or to retrieve portal configuration, and so on. As indicated earlier, a filter is independent of any given portlet, thus the portlet runtime environment (PorletContext) is not available for the filter and the portal context reference (context in Listing 2) cannot be down-casted to a PortletContext reference. Therefore, a filter can be used neither to retrieve configuration data of the target portlet, nor to invoke portlet service, both of which are available for a PortletContext object, but not for a ServletContext object.

Listing 2. Retrieve portlet filter runtime environment and configuration parameters

ServletContext context;                   
boolean trace;
public void init(PortletFilterConfig config) throws PortletException {
     //initialize the filter           
     super.init(config);
     // get portal context  
     context = config.getPortalContext();
     //get configuration parameter "Trace"   
     String param = config.getInitParameter("Trace"); 
     if ((param!=null)&&(param.equalsIgnoreCase("true"))) {
         trace = true;
     }      
     context.log("Trace = " + trace);
}

Inspect and modify the portlet request

A filter needs to examine and modify a portlet request in such cases as when:

  • Logging the data from a request.
  • Getting users who make the requests and authenticate them.
  • Retrieving and modifying the client (WML, HTML, etc.).
  • Rejecting or accepting the request based on the request content or certain parameters in the request.

The following issues need to be addressed when retrieving and modifying a portlet request:

  1. Character encoding and attributes in a request can be modified directly by calling setCharacterEncoding and set/removeAttribute methods on the PortletRequest object. For example, a call to setCharacterEncoding (ISO-8859-1) will change the character encoding of the request stream from default encoding in the user's profile (usually UTF-8) to ISO-8859-1.
  2. To modify most of the other fields in a request, you should create your own custom PortletRequest class. Your PortletRequest class should extend the PortletRequestWrapper class and override one or more methods to modify its standard behavior. For example, if the client device in a request needs to be modified, the getClient method should be overridden to return the desired client device type. If a locale field in a request needs to be modified, the getLocal method should be overridden to return the desired locale.
  3. To actually retrieve the request stream, generally you need to create your own PortletRequest class. The reason for this is that the getInputStream method on the PortletRequest object will return a null if it has already been called on this request. In other words, a call to the getInputStream method on the PortletRequest object will retrieve the data stream the first time, and then return a null value on all subsequent calls to this method. If the getInputStream method has been called for a request in a filter, a runtime NullPointerException will be thrown by the target portlet if it tries to retrieve the input stream later from the same request. A filter may first retrieve and cache the data stream from the original request, then pass the cached data stream to create a new PortletRequest object for the target portlet. The getInputStream method in your PortletRequest class should return the cached data stream.
  4. The getInputStream method on the PortletRequest object can be called only in an action event processing method (doActionEvent method). An IllegalStateException will be thrown if a filter tries to access this function outside of the action event processing.

The File Content Filter creates a FileContentPortletRequest class (Listing 3) which takes a data stream as one of the parameters in its constructor and overrides the getInputStream method to return the data stream. Thus, new FileContentPortletRequest instances can be instantiated using a data stream and the original request.

Listing 3. Custom PortletRequest class derived from PortletRequestWrapper class

public class FileContentPortletRequest extends PortletRequestWrapper {
      byte[] buffer;
      ServletInputStream input;
      public FileContentPortletRequest(PortletRequest req, byte[] buffer)  {
            super(req);
            this.buffer = buffer;                                      
      }        
           
      /** Enforce the behavior of getInputStream method in PortletRequest class: 
        * return data stream for the first call, and null for all the subsequent calls 
        */ 
      public ServletInputStream getInputStream() throws IOException  {            
            if (input == null) {
                  input = new ServletInputStreamAdapter(new ByteArrayInputStream(buffer));                                
            } else {               
                  input = null;    
            }     
            return input;                
      }
}

Listing 4 shows the doActionEvent method in the File Content Filter. This method first makes a local cache of the data stream by calling the getInputStream method on the original portlet request to retrieve the stream, then passes the cached data to the constructor of the FileContentPortletRequest class to instantiate new instances. Two instances are instantiated:

  • one is passed to the file content validation module (validateContent method, Listing 5).
  • The other is passed through the filter chain (Listing 4).

It is necessary for the File Content Filter to cache the original data stream because the Apache FileUpload library, which is used in the file content validation module, retrieves the data stream by calling the getInputStream method on the request that is passed as a parameter. If we passed the original request to the file content validation module and then passed it to the target portlet, the target portlet would not be able to get the data stream by calling the getInputStream method, and thus incur an exception. If the request contains invalid file content, the doActionEvent method saves the invalid items (InvalidItems) in the portlet session so that the doService method (in the next section, Listing 7) of the filter can retrieve the items and insert an error message into the response. The doActionEvent method itself can not insert the error message into the response, as described in the next section.

Listing 4. doActionEvent method

public void doActionEvent(PortletRequest portletRequest, PortletResponse portletResponse, 
    PortletFilterChain filterChain) throws PortletException, IOException  {
      byte[] buffer = getStreamFromInput(portletRequest.getInputStream());                                          
      Vector invalidItems = null;                    
      try {
            invalidItems = validateContent(new FileContentPortletRequest(portletRequest,buffer));
      } catch (Exception exp) {
            throw new IOException("FileContentFilter: "+ exp.getMessage());                
      }                
      PortletSession session = portletRequest.getPortletSession();
      //add invalid items to the session
      session.setAttribute("InvalidItems", invalidItems);
      if (invalidItems.size() > 0)  {                   
           //Block filter chain for invalid file content 
           filterChain.doFilter(null, null);
      } else {               
           PortletRequest newPortletRequest = new FileContentPortletRequest(portletRequest, buffer);
           //Invoke filter chain 
           filterChain.doFilter(newPortletRequest, portletResponse);
      }
      //Post processing
      context.log("FileContentFilter: current time: " + df.format(new Date(System.currentTimeMillis())));
}

Listing 5 shows the file content validation module of the File Content Filter. It uses the Apache multipart FileUpload library to retrieve the file and examine file content. It first checks if the request contains multipart content (multipart/form-data encoding type) used for file upload. If it is multipart content, the module validates the file content. For demonstration purposes, the file validation rule for the File Content Filter is very simple: it considers *.jar, *.jpg, *.gif and *.jpeg as valid file types, and all others as invalid (Listing 5).

Listing 5. File content validation module

/**Use Apache Commons FileUpload for multipart content processing
  * See http://jakarta.apache.org/commons/license.html for Apache 
  * Software License terms                      
  */
private Vector validateContent(PortletRequest portletRequest) 
      throws FileUploadException, IOException  {
      Vector invalidItems = new Vector();                    
      // check whether the request encoding type is multipart/form-data). 
      if (DiskFileUpload.isMultipartContent(portletRequest))  {                                        
            DiskFileUpload upload = new DiskFileUpload();          
            upload.setSizeMax(2000000);   //max. file size 2M               
            List items = upload.parseRequest(portletRequest);                              
            Iterator iter = items.iterator();
            while (iter.hasNext()) {
                  FileItem item = (FileItem)iter.next();
                  if (!item.isFormField())  {     
                        String fileName = item.getName();                          
                        if (!isFileContentValid(fileName))  {                        
                              invalidItems.addElement(fileName); 
                        }   
                  }
            }     
      }
      return invalidItems;
}
     
private boolean isFileContentValid(String fileName)  {        
      /**Add the logic to validate the file. 
        *For this demo, we only accept jar, jpg, gif and jpeg 
        *return true if file is valid, false otherwise. See attached 
        *source code for implementation
       */
}

Buffer the response stream

A filter that is used to modify a portlet response must usually capture the response before it is returned to the client so that the filter can manipulate it. A typical way to do this is to pass the portlet a reference to an output stream. After the portlet writes the response to the output stream, the filter can then modify the stream using the reference. In order to pass the output stream reference to the portlet, you need to create a custom PortletResponse class that extends the PortletResponseWrapper class and overrides the getWriter (or getOutputStream) and toString methods. The getWriter or getOutputStream method returns a writer, or an output stream, and the toString method returns a string representation of the output stream. The File Content Filter uses this approach to create the FileContentPortletResponse class (Listing 6).

Listing 6. Custom PortletReponse class derived from PortletResponseWrapper class

public class FileContentPortletResponse extends PortletResponseWrapper  {
      protected CharArrayWriter charWriter;
      private ServletOutputStream stream;
      protected PrintWriter writer;        
      public FileContentPortletResponse(PortletResponse resp)  {
            super(resp);            
      }        
           
      //Return an output stream that writes to a buffer
      public ServletOutputStream getOutputStream()  throws IOException  {
            //Can't call getOutputStream if getWriter has already been called
            if (writer != null)  {
                  throw new IllegalStateException("getWriter already called");
            }            
            stream = super.getOutputStream();
            return stream;
      }
           
      //Return a PrintWriter that writes to a buffer
      public PrintWriter getWriter() throws IOException {
            if (writer != null)  {
                  return writer; 
            }
            //Can't call getWriter if getOutputStream has already been called
            if (stream != null)  {
                  throw new IllegalStateException("getOutputStream already called");
            }
            charWriter = new CharArrayWriter();                     
            writer = new PrintWriter(charWriter);
            return writer;
      }       
              
      public String toString()  {
            String str = null;
            /**Only return a string if the writer was used.  
              *If the ServletOutputStream was used, it may not be encoded correctly
              */
            if (writer != null) {
                  str = charWriter.toString();
            }
            return str;
      }
}

Care must be taken to capture and modify a response while performing event processing; you cannot capture and modify a response in an event processing method (doActionEvent or doMessageEvent method) because the response is always null. Recall from portlet programming that you process an event either in the actionPerformed method for an action event or the messageReceived method for a message event; once the event processing is done, the container will invoke the service method on the same portlet to render the content. Therefore, you should capture the response from the doService method in a filter even though your filtering logic for the request is in the doActionEvent or doMessageEvent method.

Invoke or block the filter chain

A call to the doFilter method on the PortletFilterChain object invokes the next filter in the filter chain or target portlet. The parameters passed to the doFilter method are custom implementations of PortletRequest and PortletResponse, if the request and response are to be modified. The target portlet will use the custom PortletRequest and PortletResponse objects, rather than the original ones, for processing. If a request needs to be blocked for an invalid request, either no call to the doFilter method should be made, or null parameters should be passed to the doFilter method as in the statement:

filterChain.doFilter(null, null)

If a request is blocked, the filter is responsible for filling out the response. If this happens in an event processing method (doActionEvent or doMessageEvent), the response should be filled in the doService method of the filter.

Listing 7 shows the capturing and modification of the response in the doService method of the File Content Filter. It decides if the request should be forwarded or blocked based on whether or not the request contains invalid file content, which was set in the doActionEvent method earlier as a session variable (InvalidItems, Listing 4). If the request contains invalid file content, it first blocks the request by passing null as parameters to the doFilter method and then modifies the response by inserting an error message with the invalid file names. If the request is valid, it simply passes the original request through the chain.

Listing 7. The doService method

public void doService(PortletRequest portletRequest, PortletResponse portletResponse, 
    PortletFilterChain filterChain) throws PortletException, IOException  {
      PortletSession session = portletRequest.getPortletSession();
      //retrieve session variable to see if the request contains invalid files
      Vector invalidItems = (Vector)session.getAttribute("InvalidItems");
      //if the file content is valid, forward to request to next filter in the chain 
      if ((invalidItems==null)||(invalidItems.size()==0)) {
            //Invoke filter chain using original request and response
            filterChain.doFilter(portletRequest, portletResponse);          
      } else  { //if the file content is not valid, print an error message with invalid file names            
            String errMsg = "<font color='red'>Error: invalid file content: ";
            for (int i=0; i < invalidItems.size(); i++) {                                      
                  errMsg += (String)invalidItems.elementAt(i)+"<p>";                                         
            }      
            errMsg += "</font>";
            session.removeAttribute("InvalidItems");                                          
            //Buffer response stream
            PortletResponse newPortletResponse = new FileContentPortletResponse(portletResponse);      
            //Invoke filter chain using custom response object
            filterChain.doFilter(portletRequest, newPortletResponse);
            //Modify the response
            String response = newPortletResponse.toString();          
            String newResponse = errMsg + response;
            //Output modified response using original writer
            PrintWriter writer = portletResponse.getWriter();         
            writer.println(newResponse);                                        
      }           
      //Post processing
      context.log("FileContentFilter: current time: " + df.format(new Date(System.currentTimeMillis()))); 
}

Modify the response stream

After being captured, a portlet response can be modified through its string representation. You can capture the response as a string by calling the toString method on the custom PortletResponse class, which you created and passed in the doFilter method to the filter chain or the target portlet. The toString method uses the reference to the output stream you buffered in the previous step to return a string representation of the output stream in the portlet response (Listing 6). You can manipulate the response string as usual, for example, to insert or delete data or transform the string.

Output the modified response stream using the original writer

The writer from the original response, rather than from the one you created, should be used to generate the output, as in the following statements:

PrintWriter writer = portletResponse.getWriter();
writer.println("modified response string");

Post processing in a filter

If you wish, you can code the filter to do additional work, for example:

  • Log the portlet request and response.
  • Log the timestamp when the doFilter method is started and completed.
  • Notify the administrator that the request has been approved or rejected, the response has been modified, etc.



Back to top


Configure and install the portlet filter in WebSphere Portal

To plug the portlet filter into the portal server, first copy the corresponding class files to PORTAL_HOME\shared\app, register the filter to the server, and then install the filter for each of the target portlets. For the FileContentFilter in the example to work, you also need to download FileUpload components from Apache Jakarta Commons and put the JAR file (commons-fileupload-1.0.jar is used in our example) in your classpath. Restart the portal server to reload the class and property files. Refer to WebSphere Portal Information Center for Version 5.0 for filter configuration details.

We register our File Content Filter by adding its properties (Listing 1) to the PortletFilterService.properties file in the PORTAL_HOME\shared\app\config\services directory in WebSphere Portal V5. You can change the filter name, but make sure that both the filter name and the value it is paired with are unique.

To install the File Content Filter to the PDM portlet:

  1. In WebSphere Portal, select Administration => Portlets => Manage Portlets => Select Document Manager => Modify Parameters.
  2. Add FilterChain and FileContentFilter as a name/value pair.
  3. Select Add, then Save.

To view the result of the PDM portlet with the File Content Filter:

  1. Select My Portal => Documents.
  2. Select the Update Document tab.
  3. Select Upload a new document, then Next.
  4. Navigate to the selected file on your local system, then OK to submit.

By our validation rule in the demo code, if the file is valid (*.jar, *.jpg, *.gif or *.jpeg file type), it will be uploaded and listed as the PDM portlet does normally (Figure 3). If the file is invalid, then it shows an error message and the file is not uploaded (Figure 4).


Figure 3. Upload a valid file (EmailReader.jar) using PDM portlet with the File Content Filter
Figure 3. Upload a valid file (EmailReader.jar) using PDM portlet with the File Content Filter

Figure 4. Upload an invalid file (share.exe) using PDM portlet with the File Content Filter
Figure 4. Upload an invalid file (share.exe) using PDM portlet with the File Content Filter


Back to top


Conclusion

We have examined one of the most powerful portlet features in WebSphere Portal. Portlet filters enable portal developers and solution integrators to provide a quick solution for adapting and customizing existing portlets to their portals by modifying the portlet request and response, as well as adding new functions to existing portlets. We developed a File Content Filter that adds a fine-grained control mechanism to existing file upload portlets. Developers should be able to apply the information presented here in creating their own filters, using these guidelines and the downloadable source code as examples.



Back to top


Acknowledgement

The author wishes to thank his manager, Edward Rozmiarek, for his encouragement, support and time reviewing this article.




Back to top


Download

NameSizeDownload method
PortletAdapter.ZIP10 KBFTP|HTTP
Information about download methods


Resources



About the author

Shunguo Yan is a Staff Software Engineer in the Application and Integration Middleware (AIM) division of IBM software group in Austin. His major responsibility is to design and develop integrated solutions to various industries using J2EE, XML, Web Service and IBM software products.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top