Chapter 22. Ajax

Julien Viet

This section covers the ajax features provided by the portal.

22.1. Introduction

Todo

22.2. Ajaxified markup

22.2.1. Ajaxified layouts

Part of the Ajax capabilities are implemented in the layout framework which provide the structure for generating portal pages. The good news is that the existing layout only requires a few modifications in order to be ajaxified.

We will use as example an simplified version of the layout JSP provided in JBoss Portal 2.6 and outline what are the required changes that makes it an ajaxified layout:

<%@ taglib uri="/WEB-INF/theme/portal-layout.tld" prefix="p" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   <meta http-equiv="Content-Type" content="text/html;"/>
   <!-- inject the theme, default to the Renaissance theme if
        nothing is selected for the portal or the page -->
   <p:theme themeName="renaissance"/>
   <!-- insert header content that was possibly set by portlets on the page -->
   <p:headerContent/>
</head>

<body id="body">
<p:region regionName='AJAXScripts' regionID='AJAXScripts'/>
<div id="portal-container">
   <div id="sizer">
      <div id="expander">
         <div id="logoName"></div>
         <table border="0" cellpadding="0" cellspacing="0" id="header-container">
            <tr>
               <td align="center" valign="top" id="header">

                  <!-- Utility controls -->
                  <p:region regionName='dashboardnav' regionID='dashboardnav'/>

                  <!-- navigation tabs and such -->
                  <p:region regionName='navigation' regionID='navigation'/>
                  <div id="spacer"></div>
               </td>
            </tr>
         </table>
         <div id="content-container">
            <!-- insert the content of the 'left' region of the page,
                 and assign the css selector id 'regionA' -->
            <p:region regionName='left' regionID='regionA'/>
            <!-- insert the content of the 'center' region of the page,
                 and assign the css selector id 'regionB' -->
            <p:region regionName='center' regionID='regionB'/>
            <hr class="cleaner"/>
         </div>
      </div>
   </div>
</div>

<p:region regionName='AJAXFooter' regionID='AJAXFooter'/>

</body>
</html>

  • <p:theme themeName="renaissance"/> should be already present as it exists since 2.4 but is even more necessary as it will inject in the page the reference to the ajax stylesheet.
  • <p:region regionName='AJAXScripts' regionID='AJAXScripts'/> should be added before any other region in the markup of the layout.
  • <p:region regionName='AJAXFooter' regionID='AJAXFooter'/> should be added after any other region in the markup of the layout.

22.2.2. Ajaxified renderers

At runtime the portal combines the layout and the renderers in order create the markup returned to the web browser. The most used render set is the divRenderer. Renderers only need a modification in the deployment descriptor to indicate that they support ajax. Here is the declaration of the default divRenderer now in 2.6:

<renderSet name="divRenderer">
   <set content-type="text/html">
      <ajax-enabled>true</ajax-enabled>
      <region-renderer>org.jboss.portal.theme.impl.render.div.DivRegionRenderer
      </region-renderer>
      <window-renderer>org.jboss.portal.theme.impl.render.div.DivWindowRenderer
      </window-renderer>
      <portlet-renderer>org.jboss.portal.theme.impl.render.div.DivPortletRenderer
      </portlet-renderer>
      <decoration-renderer>org.jboss.portal.theme.impl.render.div.DivDecorationRenderer
      </decoration-renderer>
   </set>
</renderSet>

You should notice the <ajax-enabled>true</ajax-enabled> which indicates that the render set supports ajaxification.

22.3. Ajaxified pages

The ajaxification of the portal pages can be configured in a fine grained manner. Thanks to the portal object properties it is possible to control which pages support ajax and which page do not support ajax. The administrator must pay attention to the fact that property values are inherited in the object hierarchy.

22.3.1. Drag and Drop

That feature is only effective in dashboards as it requires the offer personalization of the page layout per user. By default the feature is enabled thanks to a property set on the dashboard object. It is possible to turn off that property if the administrator does not want to expose that feature to its user.

In the file jboss-portal.sar/conf/data/default-object.xml is declared and configured the creation of the dashboard portal:

<deployment>
   <parent-ref/>
   <if-exists>keep</if-exists>
   <context>
      <context-name>dashboard</context-name>
      <properties>
         ...
         <property>
            <name>theme.dyna.dnd_enabled</name>
            <value>true</value>
         </property>
         ...
      </properties>
      ...
   </context>
</deployment>

The property theme.dyna.dnd_enabled is set to the value true which means that the dashboard object will provide the drag and drop feature.

22.3.2. Partial refresh

Partial refresh is a very powerful feature which allows the portal to optimize the refreshing of portlets on a page. When one portlet is invoked, instead of redrawing the full page, the portal is able to detect which portlets needs to be refreshed and will update only these portlets.

The portal providing partial refresh

22.3.2.1. Portal objects configuration

Like with the drag and drop feature, partial page refresh is controlled via properties on portal objects. The name of the property is theme.dyna.partial_refresh_enabled and its values can be true or false. When this property is set on an object it is automatically inherited by the sub hierarchy located under that object. By default the drag and drop feature is positionned on the dashboard object and not on the rest of the portal objects.

<deployment>
   <parent-ref/>
   <if-exists>keep</if-exists>
   <context>
      <context-name>dashboard</context-name>
      <properties>
         ...
         <property>
            <name>theme.dyna.partial_refresh_enabled</name>
            <value>true</value>
         </property>
         ...
      </properties>
      ...
   </context>
</deployment>

Note

The partial page refresh feature is compatible with the Portal API. The Portal API allows programmatic update of the state of portlets at runtime. For instance it is possible to modify the window state or the mode of several portlets on a given page. When such event occurs, the portal detects the changes which occured and will update the portlet fragments in the page.

It is possible to change that behavior at runtime using the property editor of the management portlet. If you want to enable partial refreshing on the default portal you should set the property to true directly on the portal and all the pages in that portal will automatically inherit those properties.

The default portal configured for partial page refresh

22.3.2.2. Portlet configuration

By default any portlet will support partial refreshing. When does the portal performs partial page refreshing ? By default it is enabled for action and render links with the following exceptions. In those situations, the portal will prefer to perform a full page refresh:

  • Form GET are not handled, however it should not be an issue as this situation is discouraged by the Portlet specification. It however taken in account, just in case of. Here is an example of a Java Server Page that would do one:

    <form action="<%= renderResponse.createActionURL() %>" method="get">
       ...
    </form>
    
  • Form uploads are not handled.

  • Having an interaction that deals with the MAXIMIZED window state. When a window is entering a maximized state or leaving a maximized window state, the portal will perform a full page refresh.

It can happen that a portlet does not want to support partial refreshing, in those situations the jboss-portlet.xml can be used to control that behavior. Since 2.6 an ajax section has been added in order to configure ajax features related to the portlet.

<portlet>
   <portlet-name>MyPortletNoAjax</portlet-name>
   <ajax>
      <partial-refresh>false</partial-refresh>
   </ajax>
</portlet>

The usage of the partial-refresh set to the value false means that the portlet will not be subject of a partial page refresh when it is invoked. However the portlet markup can still be subject to a partial rendering.

22.3.2.3. Limitations

Partial refreshing of portlets has limitations both on the server side (portal) and on the client side (browser).

22.3.2.3.1. Application scoped session attributes

When partial refresh is activated, the state of a page can potentially become inconsistent. for example, if some objects are shared in the application scope of the session between portlets. When one portlet update a session object, the other portlet won't be refreshed and will still display content based on the previous value of the object in the session. To avoid that, partial refresh can be desactivated for certain portlets by adding <portlet-refresh>false<portlet-refresh> in the jboss-portlet.xml file.

22.3.2.3.2. Non ajax interactions

The solution developped by JBoss Portal on the client side is built on top of DOM events emitted by the web browser when the user interracts with the page. If an interaction is done without an emission of an event then JBoss Portal will not be able to transform it into a partial refresh and it will result instead of a full refresh. This can happen with programmatic submission of forms.

<form id="<%= formId %>" action="<%= renderResponse.createActionURL() %>" method="post">
   ...
   <select onclick="document.getElementById('<%= formId %>').submit()">
   ...
   </select>
   ...
</form>