In my previous post, I discussed the key problems in using XMLHttpRequest within portlets and other similar widget-style components. The programming model used for XMLHttpRequest interferes with the way portals aggregate pages, and provide other features like inter-portlet events, state management etc. In this post, I would like to discuss the script interface XMLPortletRequest. Before we begin, note that, although I am describing this interface in the context of portals, the idea of a wrapper interface such as XMLPortletRequest over XMLHttpRequest can be used to solve a number of use cases related to widgets and browser-side components. I will discuss more about those possibilities in a later post.

XMLPortletRequest is a script interface, i.e. it is possible to implement this interface in JavaScript. This is unlike XMLHttpRequest which can only be implemented by browsers natively. Except for its name, XMLPortletRequest shares the same syntax and semantics with XMLHttpRequest. If a portlet wants to synchronously or asynchronously update its UI either through an action or a render URL, it would simply use XMLPortletRequest in stead of the XMLHttpRequest. Where as browsers implement the XMLHttpRequest interface, portals and similar aggregating applications implement the XMLPortletRequest interface, typically as a layer on top of the XMLHttpRequest.

Here is an example on how to use XMLPortletRequest.

  var request = null;
  try {
    request = new XMLPortletRequest();
  }
  catch(e) {
    request = ... ; // Obtain an XMLHttpRequest instance the usual way
  }
  request.onreadystatechange = function()
  {
    if(request.readyState == 4 & request.status == 200) {
      // Process
    }
  }
  request.open('GET', <%=url%>, true);
  request.send(null);

The code snippet above illustrates a few characteristics of the XMLPortletRequest:

  • XMLPortletRequest has the same set of fields and functions as that of the XMLHttpRequest. Here I am referring to the XMLHttpRequest interface as is being standardized by W3C and not various browser-specific implementations.
  • XMLPortletRequest follows the same semantics as that of the XMLHttpRequest. There are some minor exceptions, most of which are a result of XMLPortletRequest being a script interface. More about those below.
  • XMLPortletRequest is designed to be a replacement of XMLHttpRequest for use in portal applications. Scripts using XMLHttpRequest can be modified to use XMLPortletRequest with minimal changes. The code changes required to migrate from XMLHttpRequest to XMLPortletRequest are simple - just change new XMLHttpRequest to XMLPortletRequest.
  • If required, it is possible to write the script such that it can function within or outside a portal environment. Outside the portal environment, the script in the above example will fall back to create an XMLHttpRequest, but the rest of the code works the same.

Here is the XMLPortletRequest interface.

interface XMLPortletRequest {
    attribute EventListener onreadystatechange;
    readonly attribute unsigned short readyState;
    void open(in DOMString method, in DOMString url);
    void open(in DOMString method, in DOMString url, in boolean async);
    void open(in DOMString method, in DOMString url, in boolean async, in DOMString user);
    void open(in DOMString method, in DOMString url, in boolean async, in DOMString user, in DOMString password);
    void setRequestHeader(in DOMString header, in DOMString value);
    void send();
    void send(in DOMString data);
    void send(in Document data);
    void abort();
    DOMString getAllResponseHeaders();
    DOMString getResponseHeader(in DOMString header);
    readonly attribute DOMString responseText;
    readonly attribute Document responseXML;
    readonly attribute unsigned short status;
    readonly attribute DOMString statusText;
};

But how does this interface solve the problems discussed in my previous post?

Wrapping XMLHttpRequest

Note that the XMLPortletRequest can be implemented as a wrapper over XMLHttpRequest, and portals provide an implementation of the XMLPortletRequest. This gives the portal a chance to intercept both requests and response. It also gives portals a chance to ferry additional portal-specific data along with each request and response, and that is the key feature of the XMLPortletRequest. See figure below.

Wrapping XMLHttpRequest

In the above, the XMLPortletRequest is implemented using XMLHttpRequest. When a portlet's script submits an XMLPortletRequest, the implementation makes a request to the portal on behalf of the portlet. This request could contain any implementation specific data. The portal then wraps the portlet's response (which in this case is some JSON data) in its own response payload and returns it to its implementation in the browser. The XMLPortletRequest implementation can then return portlet's response to the portlet via its responseText or responseXML fields. In this process, it can also update other parts of the page, including UI generated by other portlets. That is the advantage of wrapping XMLHttpRequest with a semantically equivalent interface.

In the case of the event example discussed in my my previous post, updating portlet B's UI in the browser is now possible. The portal can include portlet B's UI markup in its response payload (along with portlet A's JSON data) and send to its implementation in the browser. The implementation can then update portlet B's UI, for example, by replacing the DOM node corresponding to portlet B in the document object.

Summary

The problem becomes more interesting with Ajax toolkits like Dojo, GWT, ICEFaces etc. Some of these toolkits can be modified to use XMLPortletRequest when available, so that applications using these toolkits can operate without changes. In my next post on this topic, I will discuss more about toolkit integration.

Comments

Which browser are supported the XMLPortletRequest?

Thanks.

Leave a comment