ShowTable of Contents
Jan-Paul Buchwald - Advisory IT Specialist IBM WebSphere Portal Lab Services
Hauke Juhls - Solution Architect IBM Software Services for Lotus
General Concept of Global Portlet Filters
The full description of global portlet filters can be found in the respective section of the WebSphere Application Server Information Center
. This feature is available since WebSphere Application Server version 7, but is documented in detail and supported as a public plug-point only since version 8 (meaning that you have to contact IBM for a special agreement in order to receive official full support using this concept with WebSphere Portal on Application Server 7). Although the portlet filter concept has been introduced with JSR 286, global filters work for JSR 168 and JSR 286 portlets, but not with legacy IBM API portlets (IBM API based portlets can be filtered using an alternative mechanism described in a developerWorks article
). The basic principle of global portlet filters is to package the implementations of the JSR 286 portlet filter interfaces in an application and register them with the help of a plugin.xml
file. Besides the implementation class, the plugin.xml
can specify to which portlet life cycle methods the filter applies, and a set of init parameters to configure the filter during deployment time.
Considerations for global portlet filters in a Portal context
When configuring global portlet filters in a WebSphere Portal environment, a few considerations should be spent in which situation each filter should become active. Being a global concept, each filter applies to all portlets deployed on the system. This includes all product default portlets as well as custom portlets. There is no way to influence that by configurative means. Therefore all distinctions and checks have to be realized by code in the filter implementation.
The first aspect to consider is that code executed in the init method of the global portlet filter must be written in a way that it runs anywhere and does not rely on context information or libraries that are available only to a subset of the portlets installed on the server. For example, it is not recommended to look up any WebSphere Portal portlet services since they most likely have dependencies on classes that are only available in the Portal shared library, so they will not be found for portlets directly used in the Application Server context (such as the portlets of the Integrated Solutions Console). Instead, those kinds of lookups or initialization steps should be done in a lazy manner once the code verified the correct context.
Ensuring the correct context or performing checks whether the filter should step in can be done in a couple of ways:
- Check the portal info of the portal context (request.getPortalContext().getPortalInfo()). This way, requests to portlets running in the context of WebSphere Portal can be detected by matching the portal info to a regular expression like “IBM WebSphere Portal/.*”.
- Check the context path of the current request. This allows to detect requests to the Integrated Solutions Console, which can be ignored by the filter if it is intended for the Portal only. Other distinctions might be to explicitly detect portlets that have been deployed to WebSphere Portal directly and thus all have the same context root like the Portal (by default /wps/PA...), or pre-deployed portlets with a shared context root prefix (e.g. /predeployed/...).
- Check a particular portlet preference on the portlet addressed with the current portlet request. This is the most elegant way to control the filter applicability on a per portlet basis. Portlet preferences can be set or modified during runtime in the Portal admin interface or using the XML configuration interface.
The attached sample code contains implementation examples for all of these concepts to control filter execution.
It is the responsibility of the developer who writes the filter to choose the method that matches the use-case. For example in the scenario described below, the 3rd option using the portlet preference is very well suited as it allows to select individual portlets for filtering.
An example that matches the 1st option could be post-processing portlet output to filter for certain keywords.
Another aspect to consider when filtering calls to the render method of portlets is the two-phase rendering feature. This capability is available starting with WebSphere Portal 7, and enables the usage of the container runtime option javax.portlet.renderHeaders
that causes the render method to be invoked twice per request, once to allow the portlet to set response headers first and once to render the actual markup (see section PLT.18.104.22.168 of the JSR 286 specification
). If a portlet makes use of two-phase rendering, the portlet filter for the render phase is called twice. Therefore the filter implementation should include a check for the render headers phase (by checking the respective request attribute) and return without writing any markup in this case. The sample in the scenario also contains an example how to do this.
Description of the Sample Code
The sample filter realizes a mechanism that allows to switch particular portlets into a maintenance mode where only markup with a maintenance message is displayed instead of regular invocation of the portlet . A typical use case is that there are maintenance activities or downtimes on a critical backend system that is used by particular portlets, and you want to avoid that there are a lot of failing backend calls in the portlet involving error messages or timeouts for the end user. After deploying the filter, single portlets can be switched to maintenance mode during runtime by setting a portlet preference. In addition to returning a maintenance message for the render method, the portlet filter makes sure that none of the other portlet life cycle methods is called when the preference is set.
The following picture gives an example of a Portal page where the portlet on the right-hand side is switched to maintenance mode.
The sample code can be downloaded from Lotus Greenhouse
and is packaged as project interchange file for a web application project and associated enterprise application project. The resulting enterprise application can be directly deployed to the Application Server. The code has been developed with Rational Software Architect 8 and tested with both WebSphere Portal 6.1.5 on WebSphere Application Server 7 and WebSphere Portal 7.
The basic logic is contained in the filter implementation itself (Java class com.ibm.portal.sample.MaintenanceFilter). It first reads the name of the portlet preference from an input parameter in the init method. In the actual doFilter methods, the code first checks if it is running in the context of WebSphere Portal. If so, it reads the portlet preference to check whether the portlet addressed in the current request is configured for maintenance. For the render case, it writes the markup of a maintenance message to the output before quitting the normal render request processing. For the other portlet life cycle methods, it logs a warning and quits the regular request processing. If the preference is not set or a portlet outside of the Portal context is requested, the filter just dispatches to the regular execution of the respective portlet life cycle methods.