Using webdav-deploy-zip-file task

In the How to publish iWidget xml in the WebDav store entry i blogged about how to publish a widget xml file to WebDav store, there is one more alternative to achieve same thing

You can zip your widget xml and corresponding .js files into a .zip file, Example i did zip .xml and .js file for MyPreferences widget into c:/temp/MyPreferences.zip file

Then i used following configuration task to deploy the widget .xml and .js file onto WebDav


ConfigEngine.bat webdav-deploy-zip
-file -DZipFilePath=c:/temp/MyPreferences.zip -DTargetURI=dav:fs-type1/iwidgets/
MyPreference/


After deployment i used the AnyClient WebDav client to see the content of the WebDav and i could see that content of MyPreferences.zip file was expanded on WebDav folder like this



Now i can use following configuration task to register the MyPreferences widget


ConfigEngine.bat register-iwidget-
definition -DIWidgetDefinition=dav:fs-type1/iwidgets/MyPreference/MyPreferences.
xml -DPorteltUniqueName=webspherenotes.MyPreferences

How to publish iWidget xml in the WebDav store

In the Using iWidgets in portlet entry i blogged about how to use a iWidget as a portlet in websphere portal. In that example i did create a .war file containing widget and installed it on the portal server using WAS Admin console, basic idea was to make that widget xml URL addressable.

But you have one other option which is to upload the widget.xml file to WebDave store of your portal server and then use the WebDav URL for registering widget. I wanted to try that option so i started by creating a simple MyWidgets.xml file like this


<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="MyWidgets"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view" mode="view" lang="en">
<iw:content mode="view">
<![CDATA[
<div>Hello World - Published in WebDav Store</div>
]]>
</iw:content>
</iw:iwidget>


The MyWidget is very simple, it supports only VIEW mode and in VIEW mode it displays Hello World - Published in WebDav Store as markup to the user.

I did create this file in c:\temp\MyWidget folder. After that i used the AnyClient to create WebDav connection to http://localhost:!0039/wps/mycontenthandler/dav/fs-type1 URL like this



Then i used the client to copy the MyWidgets.xml to fs-types/iwidget folder like this



After copying the MyWidget.xml file to the WebDav repository i used the following configuration task to create a wrapper portlet for the widget


ConfigEngine.bat register-iwidget-
definition -DIWidgetDefinition=dav:fs-type1/iwidgets/MyWidgets.xml -DPorteltUniq
ueName=webspherenotes.MyWidget


Once the task is executed i can add the portlet to page and view it like this

Creating wires between iWidget on Portal page

In the Inter iWidget Communication entry i talked about how to create a iWidget that can publish an event as well as create iWidget that can subscribe event. Now i wanted to test this inter iWidget communication inside WebSphere Portal Server. We have two options for using widgets in WebSphere portal, first is we can directly use widgets on the Mashup Page of portal, or we can wrap the widgets in portlet and then add those portlets on a portal page.

I followed the steps in the Using iWidgets in portlet to wrap both SampleEventPublisher and SampleEventSubscriber widget into portlet and then i did add it to a portal page like this




Then i followed following steps to create wire between the portlets

Click on the Widget Edit Wire sub menu of the SampleEventSubscriber portlet


Go to receive event section and you will notice that i can not find any matching event to receive, the problem is that both events have different name



So i clicked on setting to get this dialog box where i said use portlet event types



After making changes save those changes and now you should be able to see both publisher and subscriber




After creating wire we can test it like this

Creating wires between iWidget on Mashup Page

In the Inter iWidget Communication entry i talked about how to create a iWidget that can publish an event as well as create iWidget that can subscribe event. Now i wanted to test this inter iWidget communication inside WebSphere Portal Server. We have two options for using widgets in WebSphere portal, first is we can directly use widgets on the Mashup Page of portal, or we can wrap the widgets in portlet and then add those portlets on a portal page.

I used the steps outlined in http://wpcertification.blogspot.com/2011/02/how-to-register-iwidget-for-use-on.html, to register and add widget on the Portal Mashup page



Then i followed few steps to create the wire between both widgets, these are the screen shots that i took along the way





Once the wires were create i could use them for inter widget communication like this

Inter iWidget communication

The iWidget specification has concept of Events similar to the Events in the portlet, the events allow widgets to communicate with each other. The Rational Application Developer iWidget wizard has a template for creating a iWidget that is capable fo publishing event as well as creating a iWdget that can subscribe to event.



I used the the RAD iWidget wizard to create a SampleEventPublisher widget, this widget is capable of publishing a event

<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="SampleEventPublisher" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" supportedModes="view"
mode="view" iScope="SampleEventPublisherScope">


<iw:eventDescription id="sendName" payloadType="String" description="Event to send data" lang="en" />

<iw:event id="sendEvent" description="sendName" published="true" />


<iw:resource src="SampleEventPublisher.js" id="SampleEventPublisherId" />

<iw:content mode="view">
<![CDATA[
<div> Name: <span id="name"></span></div>
<div>
<span id="nameField" class="nameField">
<input type="text" dojoType="dijit.form.TextBox"
maxlength="32" name="nameBox" id="nameBox" />
</span>
</div>
<div><input type="button" name="send" value="Send Name"
onclick="iContext.iScope().sendName()"/> </div>
]]>
</iw:content>
</iw:iwidget>


The eventDescription element declares the event that this widget can publish it also defines type of the event. The event element defines if this widget can publish event or subscribe event.

The SampleEventPublisher widget supports only view mode, in the view mode it displays a form where you can enter a name and click on Send Name button, when you do that it will pass control to the sendName() method. This is how the SampleEventPublisher.js looks like


dojo.declare("SampleEventPublisherScope", null,{
sendName:function(){
var data = {};

this.iContext.iEvents.fireEvent("sendEvent",null,data.value);

}
});


The iEvents.fireEvent() method is used for publishing the event. The Universal Test Client for iWidget provides a nice UI for check if you event publishing.



When i enter a name can click on Send Name button i can see that the data being sent in Events sent by your iWidget window.

Similarly i used the RAD iWidget wizard for creating SampleEventSubscriber.xml widget, this is how the widget xml looks like

<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="SampleEventSubscriber"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget" supportedModes="view"
mode="view" iScope="SampleEventSubscriberScope">

<iw:eventDescription id="receiveName" payloadType="String"
description="Event to receive data" lang="en" />

<iw:event id="receiveEvent" description="receiveName" handled="true"
onEvent="onReceiveName" />

<iw:resource src="SampleEventSubscriber.js" id="SampleEventSubscriberId" />

<iw:content mode="view">
<![CDATA[
<span id="helloSpan"><h1>Hello World</h1></span>
]]>
</iw:content>
</iw:iwidget>


The SampleEventSubscriber widget defines one receiveEvent of String type. In the view mode it displays Hello World message which will be changed to display value of event. The value of onEvent attribute defines name of the JavaScript method that will get called when this event receives event. This is how the JavaScript for the SampleEventSubscriber looks like


dojo.declare("SampleEventSubscriberScope", null,{
onReceiveName:function(iEvent){
var data = iEvent.payload;
if (dojo.isString(data))
var name = data;
else if (dojo.isString(data.value))
var name = data.value;
else
return;

var element = this.iContext.getElementById("helloSpan");
element.innerHTML = "

Hello " + name + "

";
}
});



The onReceiveName() will get called when this widget receives event. The widget container will pass object iEvent to the onReceiveName() method, inside this method we are reading payload of the event and displaying it to the user by changing markup of the view mode.

The Univeral test client for iWidget has a UI that lets you publish the widget and test event receiving part of your widget

Working with preferences in iWidget

The iWidget's have concept of preferences similar to portlet preferences that you can use to set and get values. I wanted to try this feature so i decided to create a simple iWidget, that will display the zipCode in the view mode and in the edit mode, it will let user change the zipCode so that the value gets saved as preference and in the view mode i will read and display the value of zipCode from preference.

This is how my SamplePreferences.xml the widget.xml file looks like

<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="SamplePreferences" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view edit" mode="view" lang="en" iScope="SamplePreferencesScope">
<iw:itemSet id="pref">
<iw:item id="zipcode" description="The zipcode "
value="94536"/>
</iw:itemSet>
<iw:resource src="SamplePreferences.js" id="SamplePreferences" />
<iw:content mode="view">
<![CDATA[
<div >Current cityCode - <span id="zipCode">notset</span></div>

]]>
</iw:content>

<iw:content mode="edit">
<![CDATA[<div>
<div> New Zip Code: <span id="name"></span></div>
<div>
<span id="zipCodeField" class="nameField">
<input type="text" dojoType="dijit.form.TextBox"
maxlength="32" name="zipCode" id="zipCode" />
</span>
</div>
<div><input type="button" name="changeZipCode" value="Change ZipCode"
onclick="iContext.iScope().changeZipCode()"/> </div>
</div>]]>
</iw:content>
</iw:iwidget>


The SamplePreferences widget supports 2 modes view and edit, the view mode markup is pretty simple it just displays the zipCode, with default value of notset. In the edit mode it is displaying a form that will take zipCode as input and once user clicks on submit button it will pass control to changeZipCode() javascript method.

The SamplePreferences has SamplePreferences.js resource associated with it, which looks like this

dojo.declare("SamplePreferencesScope", null,{
changeZipCode:function(){
console.log("Entering SamplePreferencesScope.changeZipCode()");
var zipCodeStr = this.iContext.getElementById("zipCode").value;
this.iContext.getItemSet("pref", true).setItemValue("zipcode",zipCodeStr)
console.log(this.iContext.getItemSet("pref", true));
console.log("Exiting SamplePreferencesScope.changeZipCode() " + zipCodeStr);
},

/*
This event signals that the mode for the iWidget has changed to VIEW
*/
onView:function() {
console.log("Entering SamplePreferencesScope.onView()");
this.iContext.getElementById("zipCode").innerHTML =
this.iContext.getItemSet("pref", true).getItemValue("zipcode");
console.log("Exiting SamplePreferencesScope.onView()");

}

});


The JavaScript has 2 methods one is changeZipCode() which gets called when user enters a value of zipCode in edit mode and clicks submit. In this method i am reading value submitted by user and setting it in itemSet, which is equivalent of preferences in iWidget.

The onView() is the callback method that gets called when widget is getting rendered in the VIEW mode, i am using this method to read the zipCode set by user in the edit mode and displaying it to user.

This is how the widget looks like in the EDIT mode


This is how the widget looks like in the VIEW mode

What is IWidget Wrapper portlet

The WebSphere Portal Server has a dedicated IWidget Wrapper portlet for easy integration with iWidgets. The portal unique name of this portlet is wp.p.IWidgetWrapper. Whenver you register a iWidget with portal it creates a portlet instance of the IWidget wrapper portlet.

When you register a new iWidget definition URI in your portal, the portal infrastructure loads the corresponding iWidget definition XML file and maps the information provided by the referenced iWidget definition into corresponding portlet meta data. This includes information about events and modes that the iWidget supports. The title and description of the created IWidget Wrapper clone are derived from the corresponding values of the iWidgets idescriptor item set.

I used the register-iwidget-definition task to register 3 widgets as portlets. THen i used the Manage Web Modules portlet to find the wp.resolver.iwidget.portlet.war file and inside that there were 4 instances of IWidgetWrapper portlet, one for default IWidgetWrapper portlet and 3 instances were created for three portlets that i registered.



I wanted to check what preferences get set for widget defined by following HelloWorldIWidget.xml


<?xml version="1.0" encoding="UTF-8" ?>
<iw:iwidget id="HelloWorldIWidget" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
supportedModes="view edit" mode="view" lang="en">
<iw:content mode="view">
<![CDATA[<div>Hello World - View Mode</div>]]>
</iw:content>
<iw:content mode="edit">
<![CDATA[<div>Hello World - Edit Mode</div>]]>
</iw:content>
</iw:iwidget>


When i checked the preferences for the portlet this is what i saw



As you can see the actual markup is stored in a preference

How to register a iWidget for use on Portal Mashup Page

YOu have two options to use iWidget in Portal 7.0, one either you can wrap a iWidget into portlet and then add the wrapped portlet on a portal page or you can use iWidget on the portal mash up page.

I wanted to add the widget on the Mashup Page inside the portal so these are the steps that i followed for that

  1. First install the J2EE application that contains the widgets as .war file using WAS Admin Console, while installing select WebSphere Portal as the server. Take a note of the context root of the web application

  2. Once the J2EE application is installed start the application

  3. After installing web application make sure that you can view the widget.xml files by going to the url


  4. Once the application is installed you should register it with the the portal by executing the following configuration task

    ConfigEngine.sh|bat register-mashup-module
    -DApplicationName='SampleIWidgetJ2EEApp_war'
    -DWasPassword=wasadmin
    -DPortalAdminPwd=wasadmin

    In my case the SampleIWidgetJ2EEApp_war is name of the application

  5. Next step is to change the catalog.xml file for for the toolbox to add name of the newly installed widget. To do that first you should copy the \WebSphere\PortalServer\base\wp.mmi.deploy\config\binaries\catalogs\catalog_default.xml file somewhere on your machine say c:/work.

  6. Then you should add one entry each for each of the widget like this

    <entry id="helloIWidget" unique-name="helloIWidget">
    <title>
    <!--@feedreader.title@-->
    <nls-string lang="en">Hello World iWidget</nls-string>
    </title>
    <description>
    <!--@feedreader.description@-->
    <nls-string lang="en">Displays content from a specified feed URL</nls-string>
    </description>
    <definition>/sampleiwidget/HelloWorldIWidget.xml</definition>
    <content>http://www.webspherenotes.com</content>
    <preview>http://www.webspherenotes.com</preview>
    <icon>/feedReader/feedreader.png</icon>
    <metadata name="com.ibm.lotus.widget.renderer">priority</metadata>
    </entry>

    Add the entry under the category where you want it to appear.

  7. Once the mycatalog.xml file is modified with your widget definition, you can register it with was by executing following configuration task

    ConfigEngine.bat import-config-fil
    e -DMMImportFile=c:\work\mycatalog.xml -DMMImportFilePropertyName="mashups.catal
    og_default.xml"


  8. Now restart the portal server and when you try to access the Mashup page you should be able to see the HelloWorldiWidget widget added to Demo category, you can drag and drop it on the mashup page


Ajax Test server in the RAD 8.0

The Rational Application Developer 8.0 has a Ajax Test Server, The AJAX test server is a lightweight Jetty-based server ideally suited for developing and testing AJAX applications. It quickly performs module publishing and server restart. It supports basic web artifacts such as servlets, JSP files, HTML, XML, JavaScript™ and CSS files.

You can use the AJAX test server when you want to compile, test and run resources quickly in an AJAX application, for example a Dojo-enabled web project or an iWidget project. You can test static or dynamic web projects on a AJAX test server.

In the Creating iWidget project using RAD 8 entry i mentioned the steps that you can follow to create a iWidget. Once your iWidget is ready you can test it by creating a Ajax Test Server definition and adding your iWidget application to it.



As you can see in my case i am adding SampleIWidgetJ2EEApp application to the Ajax Test Server, after adding the project you can test your application using Universal Test Client for iWidget by right clicking on the iWidget.xml and saying Run on the Server, in the server select Ajax Test Server.



The way it works is you pass the URL of your widget.xml file to the http://127.0.0.1:2341/mum/testWidget.jsp.

In my case the SampleIWidgetJ2EEApp has 3 widget definitions and they are available at http://localhost:8080/SampleIWidgetJ2EEApp/ directory so i can test each of them by passing the URL to the testWidget.jsp like this
http://127.0.0.1:2341/mum/testWidget.jsp?iWidget=http://localhost:8080/SampleIWidgetJ2EEApp/SampleEventSubscriber.xml&debug=false for testing SampleEventSubscriber.xml

The actionScopedRequestAttributes container runtime option

One common issue in working with standard compliant portlet is how do i pass data from action phase(processAction()) to render phase (render()). In order to take advantage of portlet life cycle normally we should execute the business logic to get data from back end in the processAction() method and then pass the complex object from processAction() to render() method but the problem is the we cannot pass complex object we can only pass string parameters by calling PortletResponse.setRenderParameter() method, only alternative is to use the PortletSession

The Portlet Specification introduced concept of container run time options that allows us to modify/ tune behavior of the portlet container. It introduced a javax.portlet.actionScopedRequestAttributes which is set to false by default, but if you set its value to true then you can set request attribute in the processAction() method and you should be able to access those request attributes in the render() method. These request attributes will be preserved until the next action or event request. One drawback of this approach is the request attributes are stored in PortletSession under the hood and it has performance implications of storing data in portlet session, but positive side this approach is better than storing and removing objects in session by yourself.


I wanted to try this feature so I did create ActionScopeRequestAttributePortelt portlet.

This is how my portlet.xml file looks like

<?xml version="1.0" encoding="UTF-8"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
id="com.webspherenotes.jsr286.ActionScopeRequestAttributePortlet.78dbf213e2">
<portlet>
<portlet-name>ActionScopeRequestAttribute</portlet-name>
<display-name xml:lang="en">ActionScopeRequestAttribute</display-name>
<display-name>ActionScopeRequestAttribute</display-name>
<portlet-class>com.webspherenotes.jsr286.ActionScopeRequestAttributePortlet</portlet-class>
<init-param>
<name>wps.markup</name>
<value>html</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<portlet-info>
<title>ActionScopeRequestAttribute</title>
<short-title>ActionScopeRequestAttribute</short-title>
<keywords>ActionScopeRequestAttribute</keywords>
</portlet-info>
</portlet>
<default-namespace>http://ActionScopeRequestAttribute/</default-namespace>
<container-runtime-option>
<name>javax.portlet.actionScopedRequestAttributes</name>
<value>true</value>
<value>numberOfCachedScopes</value>
<value>10</value>
</container-runtime-option>
</portlet-app>


As you can see the value of actionScopedRequestAttributes is set to true. THis is how the portlet code looks like

package com.webspherenotes.jsr286;

import java.io.IOException;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class ActionScopeRequestAttributePortlet extends javax.portlet.GenericPortlet {
public void doView(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
// Set the MIME type for the render response
response.setContentType(request.getResponseContentType());
System.out.println("doView(), Exiting Value of request attribute"
+ request.getAttribute("userName"));

PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/action.jsp");
rd.include(request,response);

}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException, java.io.IOException {
System.out.println("processAction(), Exiting Value of request attribute"
+ request.getAttribute("userName"));
System.out.println("Setting request attribute userName to "
+ request.getParameter("userName"));
request.setAttribute("userName", request.getParameter("userName"));
}

}


In the processAction() method i am storing the value of userName submitted by the user as request attribute and then in the .jsp i am just reading the values from renderRequest and display it to user like this


<%@page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" session="false"%>
<%@taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0"%>
<portlet:defineObjects />
<portlet:actionURL var="actionUrl">
<portlet:param name="action" value="submit" />
</portlet:actionURL>
<form method="post" action="<%=actionUrl %>">
<table>
<tr>
<td>Value stored in request attribute</td>
<td colspan="2">
<%=renderRequest.getAttribute("userName") %>
</td>
</tr>
<tr>
<td>User Name</td>
<td><input type="text" name="userName" /></td>
<td><input type="submit" name="submit" value="Submit" /></td>
</tr>

</table>
</form>


I tried this code in WPS 7.0 and it worked, so i used the How to inspect the values stored in the Portlet Session to check the PortletSession and i can see the com.ibm.ws.portletcontainer.core.action_scope_cache attribute in the PORTLET_SCOPE

How to inspect the values stored in the Portlet Session

In the How to check what objects are stored in HttpSesession entry i mentioned about how to use the com.ibm.ws.webcontainer.httpsession.SessionInspectServlet servlet for inspecting content of a servlet.

The PortletSession object is based on HttpSession, with difference that when you store attribute in the PortletSession in PORTLET_SCOPE , the portal server will name space that attribute and store it in the HttpSession, You can also set an attribute in the PortletSession using APPLICATION_SCOPE it will be stored in the HttpSession without any name spacing.

The side effect of this layering is we can use the same SessionInspectionServlet for inspecting content of a PortletSession.

If you want to use SessionInspectionServlet then you need to make sure that value of enable-serving-servlets-by-class-name is set to true in your ibm-web-ext.xmi file. By default when you create a portlet this value is set to true(You might to add a step to set enable-serving-servlets-by-class-name to false in your security hardening procedure). You can check this value by going to WebSphere\wp_profile\installedApps\\.ear\Contact.war\WEB-INF\ibm-web-ext.xmi for portlet that is installed on your portal, for the portlets that your running through the RAD just check that value in portlet application inside your workspace.

Once you ensure that enable-serving-servlets-by-class-name is set to true the next step would be to figure out the context path of your portlet .war file. You can do this by looking at ibm-web-ext.xmi file of the portlet that you deploy through RAD


<?xml version="1.0" encoding="UTF-8"?>
<web-ext
xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
version="1.0">

<reload-interval value="3"/>
<context-root uri=".ActionScopeRequestAttribute" />
<enable-directory-browsing value="true"/>
<enable-file-serving value="true"/>
<enable-reloading value="true"/>
<enable-serving-servlets-by-class-name value="true" />

</web-ext>


Value of uri attribute in context-root element defines the context-root of your web application.

If your portlet is installed using Portal admin console then you will have to look inside the application.xml in the WebSphere\wp_profile\installedApps\\.ear\META-INF folder


<?xml version="1.0" encoding="UTF-8"?><application id="Application_ID" version="5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd">
<display-name>Contact_war</display-name>
<module>
<web>
<web-uri>Contact.war</web-uri>
<context-root>/wps/PA_Contact</context-root>
</web>
</module>
</application>


The value of context-root is used for defining the context-root of your portlet. Once you know the context-root go to http://localhost:10039/context-root/servlet/com.ibm.ws.webcontainer.httpsession.SessionInspectServlet URL for inspecting value of the servlet.

In order to test this feature i did create a portlet that sets one session attribute in PORTLET_SCOPE and other session attribute in APPLICATION_SCOPE, i did hit the portlet so that the values get set in PorteltSession, this is how my code looks like


request.getPortletSession().setAttribute("applicationScopeAttribute",
"testValue",PortletSession.APPLICATION_SCOPE);
request.getPortletSession().setAttribute("portletScopeAttribute",
"testValue",PortletSession.PORTLET_SCOPE);



Now in the same browser i did open another tab and when i did hit the SessionInspection servlet this is what i see



As you can see the attribute stored in APPLICATION_SCOPE gets stored as it is. But for the attribute that is stored in PORTLET_SCOPE the portal server will add javax.portlet.p.<portletwindowid>? prefix

Enabling mashup ui on portal

Starting from version 7.0, the WebSphere portal ships with Mashup integration, you can use the Mashup to execute iwidgets. The Mashups are not installed in the base portal installation so you will have to enable them

You can enable the mashup ui by executing ConfigEngine.sh|bat deploy-portal-mashup-ui -DWasPassword=was_password -DPortalAdminPwd=portal_password task. After enabling mashups restart the portal and now when you login you should see My Mashups link on the top next to Home page like this



If you click on the Mashup's link it will take you to Mashup's page which looks like this



You should be able to add iWidgets to this page and wire them to each other.

SessionTimeoutFilter, for executing some logic when your portal session is timedout

If you want to execute some logic when user session times out Ex, some cleanup logic that you want to call when user logs out, then you can implement SessionTimeoutFilter. This filter is called immediately after the session of a user has been destroyed either by an idle timeout or by an invalidation of the session (e.g. due to a mismatch of session and request user). It is not called when the user is logged out properly.

I wanted to try this feature so i did create a simple SessionTimeoutFilter that will print out name of the user who's session is getting timed out. Note that you dont get access to HttpServletRequest object so you will have to pass that name as HttpSession attribute, set it using LoginFilter and then read the name in the SessionTimeoutFilter


package com.webspherenotes.auth;

import java.util.Map;

import javax.servlet.http.HttpSession;

import com.ibm.portal.auth.SessionTimeoutFilter;
import com.ibm.portal.auth.SessionTimeoutFilterChain;
import com.ibm.portal.auth.exceptions.UserSessionTimeoutException;
import com.ibm.portal.security.SecurityFilterConfig;
import com.ibm.portal.security.exceptions.SecurityFilterInitException;

public class SampleSessionTimeoutFilter implements SessionTimeoutFilter{
public void destroy() {
}

public void init(SecurityFilterConfig arg0)
throws SecurityFilterInitException {
}
public void onUserSessionTimeout(HttpSession session, Map map,
SessionTimeoutFilterChain filterChain) throws UserSessionTimeoutException {
System.out.println("Inside SampleSessionTimeoutFilter.onUserSessionTimeout SessionId "
+ session.getId());
System.out.println("Inside SampleSessionTimeoutFilter.onUserSessionTimeout, User Name "
+ session.getAttribute("userName"));
filterChain.onUserSessionTimeout(session, map);
}
}

Use SessionValidationFilter for executing logic before every page

The SessionValidationFilter allows you to execute business logic before action is requested and page is rendered. This method will get executed once for every page. You can use this method to redirect user to different page, generate some debugging information. Ex. lets say you have a requirement that every time a page gets rendered you will have to check if the page is empty(no portlets), if yes redirect user to different page.

I did create this SampleSessionValidationFilter that prints out the request and session information for the portal before every request.


package com.webspherenotes.auth;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.ibm.portal.auth.FilterChainContext;
import com.ibm.portal.auth.SessionValidationFilter;
import com.ibm.portal.auth.SessionValidationFilterChain;
import com.ibm.portal.auth.exceptions.SessionValidationException;
import com.ibm.portal.security.SecurityFilterConfig;
import com.ibm.portal.security.exceptions.SecurityFilterInitException;

public class SampleSessionValidationFilter implements SessionValidationFilter{

@Override
public void destroy() {

}

@Override
public void init(SecurityFilterConfig arg0)
throws SecurityFilterInitException {

}

@Override
public void validateSession(HttpServletRequest request,
HttpServletResponse response, FilterChainContext filterChainContext,
SessionValidationFilterChain filterChain)
throws SessionValidationException {
System.out.println("Inside SampleSessionValidationFilter.validateSession() User Name"
+ request.getRemoteUser());

System.out.println("Printing request attributes");
Enumeration attributeNameEnum = request.getAttributeNames();
while(attributeNameEnum.hasMoreElements()){
String attributeName = attributeNameEnum.nextElement();
System.out.println(attributeName +" " + request.getAttribute(attributeName));
}
System.out.println("Printing request parameters " + request.getParameterMap());

HttpSession session = request.getSession();
System.out.println("Printing request attributes");
Enumeration sessionAttributeNameEnum = session.getAttributeNames();
while(sessionAttributeNameEnum.hasMoreElements()){
String attributeName = sessionAttributeNameEnum.nextElement();
System.out.println(attributeName +" " + session.getAttribute(attributeName));
}

filterChain.validateSession(request, response, filterChainContext);

}
}


You will have to implement SessionValidationFilter interface and then you will get control inside validateSession method before the page gets rendered.

The class file for filter should go to the shared library of the server. Dont forget to register your validate sesion filter with by portal using WS_AuthenticationService

Use LogoutFilter to execute some logic, cleanup when user logs out

In the Creating loginfilter for WebSphere Portal document i mentioned steps for creating and configuring filter that lets you execute some code during the login process.

Similarly there could be requirement to extend the logout filter, Ex. you might want to cleanup the user related or user's session related entries from the DynaCache, if that's the case then you should create a LogoutFilter

Take a look at the SampleExplicitLogoutFilter that i created, which prints name of the user who is login out from the portal

package com.webspherenotes.auth;

import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.portal.auth.ExplicitLogoutFilter;
import com.ibm.portal.auth.FilterChainContext;
import com.ibm.portal.auth.LogoutFilterChain;
import com.ibm.portal.auth.exceptions.LogoutException;
import com.ibm.portal.security.SecurityFilterConfig;
import com.ibm.portal.security.exceptions.SecurityFilterInitException;

public class SampleExplicitLogoutFilter implements ExplicitLogoutFilter{

@Override
public void destroy() {

}

@Override
public void init(SecurityFilterConfig arg0)
throws SecurityFilterInitException {
}

@Override
public void logout(HttpServletRequest request, HttpServletResponse response,
FilterChainContext filterChainContext, LogoutFilterChain filterChain)
throws LogoutException, LoginException {
System.out.println("Inside SampleExplicitLogoutFilter.LoutoutFilter() RemoteUser"
+ request.getRemoteUser());
filterChain.logout(request, response, filterChainContext);

}

}


In order to create a LogoutFilter you will have to implement ExplicitLogoutFilter interface and then the logic that you want to execute during logout phase should go to logout() method.

The class file for filter should go to the shared library of the server. Dont forget to register your logout filter with by portal using WS_AuthenticationService

Controlling memory size of DynaCache

One of the common problems with using caching frameworks is how do you control the size of the memory taken by the cache. Most of the caches allow you to control number of entries that should be cached, but not the maximum memory size of the cache. So it might happen that your cache will grow too big and cause memory issue for your application/application server.

Starting with WebSphere Application Server 7.0, you can control what is the maximum memory that your cache instance can take. I wanted to create cache instance and set its size to 10MB and start putting objects in the cache and make sure that the cache does not grow above 10MB. YOu can download the sample application from here

First i went into the WAS Admin Console and i did create a new cache instance SampleMemInstance and bound it at services/cache/samplememcache JNDI location like this,



As you can see i did configure maximum number of entries to 20k and maximum mem size to 10MB

Then i did create a new Web SampleDynaCacheMemSize web application, which has a servlet that takes number of entries that should be put in cache as argument and starts adding those entries in cache like this


package com.webspherenotes.dynacache;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.websphere.command.CommandException;

/**
* Servlet implementation class SampleDynaCacheMemSize
*/
public class SampleDynaCacheMemSize extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
int startIndex = Integer.parseInt(request.getParameter("startIndex"));
int number = Integer.parseInt(request.getParameter("number"));
for(int i = startIndex ; i < startIndex + number ; i++ ){
System.out.println("Putting object in cache for key " + i);
SampleMemObject sampleMemObject = new SampleMemObject(i);
try {
sampleMemObject.execute();
} catch (CommandException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}


Then the last piece is to create a SampleMemObject CacheableCommand object like this


package com.webspherenotes.dynacache;

import com.ibm.websphere.cache.Sizeable;
import com.ibm.websphere.command.CacheableCommandImpl;


public class SampleMemObject extends CacheableCommandImpl implements Sizeable{
/**
*
*/
private static final long serialVersionUID = 1027837849378068229L;
private int cacheKey;

public SampleMemObject(int cacheKey){
this.cacheKey = cacheKey;
}

@Override
public long getObjectSize() {
return 1048576;
}

@Override
public boolean isReadyToCallExecute() {
return true;
}

@Override
public void performExecute() throws Exception {
System.out.println("Inside SampleMemObject.performExecute()");
}

public int getCacheKey() {
return cacheKey;
}

public void setCacheKey(int cacheKey) {
this.cacheKey = cacheKey;
}

}


If you want to control size of memory then you should implement Sizeable interface in your Command object and implement getObjectSize() method, this method returns a long value with size of object, in my case i am returning a value which is equal to 1 MB.

After deploying the code i did execute the servlet like this http://localhost:9080/SampleDynaCacheMemSize/SampleDynaCacheMemSize?startIndex=0&number=11, and asked it to put 11 entries in cache at that time i could see that following message is being return to the SystemOut.log because memory size is full, the message wording is wrong it should have said memory size is reached.


[2/14/11 6:11:49:718 PST] 00000018 Cache A DYNA1070I: Cache instance "services/cache/samplememcache" is full and has reached the maximum configured size of 200000 entries. Space on the JVM heap for new entries will now be made by evicting existing cache entries using the LRU algorithm. Please consider enabling the disk offload feature for the cache instance to prevent the discard of cache entries from memory.

How to use custom servlet cache instance for Custom Java Objects

In the Storing custom java objects in Dynacache using CachableCommand entry i talked about how to use the DynaCache for storing the custom java object, similarly you can use the DynaCache for caching output of a portlet or servlet

By default websphere application server creates one instance of cache(you can think of cache instance as bucket) baseCache and that cache instance is used for storing all the custom java objects, output of servlet, output of portlet. But what if you want to have more granular control over the cache instance. Ex. you want to cache say up to 2000 instances of custom java object or you want to make sure that only 10mb size is used for storing servlet output. In order to solve those advanced use cases you should create separate cache instance.

I wanted to try how to use a separate cache instance for my storing custom java object, so first i went to WAS Admin Console and i did define a new Servlet cache instance like this



When you create a new cache instance you can define things like the JNDI name where the instance would be bound, also Cache size, which means how many objects would be stored in the cache. In my case i am using default cache size of 2000 and then i am setting JNDI name for the cache instance to be services/cache/samplecache.

I can configure my Sample application for storing custom java object to use the services/cache/samplecache by making one change in the cachespec.xml file like this


<?xml version="1.0" ?>
<!DOCTYPE cache SYSTEM "cachespec.dtd">
<cache>
<cache-instance name="services/cache/samplecache">
<cache-entry>
<class> command</class>
<sharing-policy>not-shared</sharing-policy>
<name> com.webspherenotes.cache.CacheableContact.class</name>
<cache-id>
<component type="method" id="getContactId">
<required>true</required>
</component>
<priority>1</priority>
<timeout>180</timeout>
</cache-id>
</cache-entry>
</cache-instance>
</cache>


You can configure the cache-entry to use different cache-instance by enclosing it in cache-instance element where value of name attribute should be equal to the JNDI name where the cache instance is bound, the same name that you used while configuring the cache instance

After making the change i did execute the servlet so that the CacheableContact objects is set in cache, now i can see that instance using cache monitor

How to check what objects are stored in HttpSesession

You might want to check what objects are stored in HttpSession because either your application is throwing java.io.NotSerializableException or during performance testing you want to check size of the objects stored in session.

The WebSphere Application Server ships a com.ibm.ws.webcontainer.httpsession.SessionInspectServlet servlet that can be used to find out what is content of the session as well as size of the objects stored in session. The SessionInspectionServlet is part of AppServer/plugins/com.ibm.ws.webcontainer.jar, which is already on your web applications class path. So in order to use the SessionInspectionServlet, you will have two choices

  1. Define the SessionInspectionServlet in your web.xml and map it to a URI

  2. Enable Serving servlets by class name, you can set this value in the ibm-web-ext.xml



    <?xml version="1.0" encoding="UTF-8"?>
    <web-ext
    xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
    http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
    version="1.0">

    <reload-interval value="3"/>
    <enable-directory-browsing value="true"/>
    <enable-file-serving value="true"/>
    <enable-reloading value="true"/>

    <enable-serving-servlets-by-class-name value="true" />

    </web-ext>



After making this change restart your web application and then access your web application so that the attributes/ objects are added into HttpSession, once that part is done you can access the SessionInspectionServlet and it will show you output like this




In my case i did create a simple SessionInspectionServletDemo servlet like this

package com.webspherenotes.session;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
* Servlet implementation class SessionInspectionServletDemo
*/
public class SessionInspectionServletDemo extends HttpServlet {
private static final long serialVersionUID = 1L;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.getWriter().println("Inside SessionInspectionServletDemo");
HttpSession session = request.getSession();
session.setAttribute("testName", "testValue");
Contact c = new Contact();
session.setAttribute("contact", c);

}
}


Inside the doGet() method i a am adding a testName attribute with String value and a contact attribute with object of non Serializable Contact object as value.

I made changes in the Contact object to implement java.io.Serializable interface and now i can see that the SessionInspectionServlet servlet does not list it under the Non-Seiralizable object and it also shows the size of the session