Skip to main content

Client Side Eventing

[ download the sample (binary and source) ]

Consider a JSR-286 Java portlet which uses AJAX on client-side for actions. This typically calls the serveResouce method of the portlet which does not generate server side 286 events. Even if there is another 286 Java portlet, it can not leverage server-side eventing. Additionally, there may be other non-Java widgets on the page and all of these will work in silo in the absence of client-side eventing. On the other hand, if there is a framework to generate and propagate events on client, then this can benefit enormously. This design tries to mimic JSR-286 based eventing (which is defined for Portlet Container) on the client.

Consider a typical AJAX portlet which generates events. Although this portlet can be written in various ways, the example shown below tries to follow the pattern and conventions set by JSR-286 spec for Java portlets.

Assume there is a button that causes an action on the portlet. This will look something like below,

<input name="getbtn" id="getbtn" value="Get Something" type="button" 
onclick="<portlet:namespace>PortletObj.processAction('<portlet:resourceURL id="i1"/>')"/>

Notice above that there is a Javascript object with name that has been namespaced using JSR 286 tag to make it unique. Such a process action method for the JS object may be implemented as shown below,

    processAction : function(updateURL) {
        portletReq = new XMLPortletRequest("<portlet:namespace/>");

        portletReq.onreadystatechange = function() {<portlet:namespace/>PortletObj.render();};"POST", updateURL);
        portletReq.send("formData=" + someData);

The callback is set to a render method on this portlet object as shown below,
    render : function() {
        // process response
        var div = document.getElementById("<portlet:namespace/>portletData");
        div.innerHTML = "";
        div.innerHTML = portletReq.responseText;

        var qName = { uri : "" , name : "SomeEvent" };

        var values = {
            value : [{"foo" : bar}]

portletReq.setEvent(qName, values);      

The most important thing to note is the event generation above. As per the 286 spec, setEvent could have been called in the processAction method. This would work if this was a simple case where some form data (which is ready at the time processAction is called), was to be passed on to the consumer of the event. If the event payload is more than the form data and if it is actually a result of data returned by the AJAX call to the portlet, then triggering the event needs to be postponed till this data becomes available. That means the event data will be available asynchronously when the callback is invoked. Or the event payload may even be returned as a JSON object or constructed as such. Hence the deviation from the 286 spec to set the event in render.

The deployment descriptor for the portlet specifies the event as per the JSR-286 spec. The only difference is the "value-type" which uses a dummy marker com.sun.portlet.ClientEvent.

       <qname xmlns:x=””>x:SomeEvent</qname>
    <qname xmlns:x=””>x:SomeEvent</qname>

This tells the portlet container that the portlet uses client-side eventing. The wiring of the portlets is handled by the portlet container in the exact same way as it would have been done for the server-side eventing(i.e based on the deployment descriptor information). This happens transparently to the developer.

Thus, whenever the generator portlet calls setEvent, the event queue distributes the event object (payload) to all the portlets that support processing the event. This is also done in the deployment descriptor of the portlet as specified in JSR-286 spec and shown below.

       <qname xmlns:x=””>x:SomeEvent</qname>

The event processing portlet has to implement a method processEvent as shown below.

    processEvent : function (values) {

How the processEvent method is implemented is up to the portlet developer.

Check the sample(binary and source) that showcases the Client Side Eventing.


Please Confirm