You have heard the buzz about Ajax and you are wondering if you can use it in your portal application. Well, you can, and this article tells you how to get started. One of the most expensive actions in a portal is refreshing pages. You can use Ajax to handle many user interaction events and then to apply the updates to portions of the page, without requiring a full page refresh. You can improve your portal's performance, create a cleaner overall portal application architecture, and, most of all, make your users happier with such a responsive portal.

Share:

Karl Bishop (kfbishop@us.ibm.com), Senior Software Engineer, IBM

Photo: Karl BishopKarl Bishop is a Senior Software Engineer on the IBM Web Enablement and Support team. He works from the wilds of North Carolina. Karl works on various internal and external Web 2.0 and Mobile applications. He specializes in Dojo, Dojo Mobile, and Worklight based solutions.



Doug Phillips (dougep@us.ibm.com), Advisory Software Engineer, IBM

Doug PhillipsDoug Phillips is an Advisory Software Engineer for IBM's elite group of skilled professionals known as IBM's Web Enablement and Support team. He has worked in many organizations within IBM and currently designs and develops both internal and external WebSphere Portal applications using IBM middleware and Linux. Doug is WebSphere and DB2 certified.



28 June 2006

Also available in Chinese

Introduction

This article introduces you to the idea of integrating Ajax into your portal applications. Because there are several general Ajax articles already available (see Resources), we assume you understand the basics of Ajax; that is, you already know what Ajax means, how it got its name, the fact that it's not new, and how Google brought this technology into the mind set of every executive and technologist on the planet. Our intention is to equip you with useful information related to using Ajax in your portal applications, so when the call comes down from the CTO's office asking if your portal applications are Ajax enabled, you can stand up and say, "You bet!"

So what this article describes are areas to consider if you decide to inject Ajax into your portal. While the focus is on portal applications, these tips are generally applicable to most complex applications. This article also prepares you for a future tutorial, in which we will detail the creation of an Ajax portlet application.

One quick rant, before we get back to the topic at hand: much of what you see and read about Ajax is not really Ajax; it's Dynamic HTML, or DHTML. Ajax, in its proper sense, consists of a single JavaScript object called XMLHttpRequest. This class provides a background communication channel to a server and for the resulting response. Everything else, including drag-and-drop, DOM updates, styling, and all the other things that make everyone go "ohh and ahh", is DHTML.


Why Ajax and WebSphere Portal are a good fit

One of the most expensive actions in a portal environment is to refresh the page. When the user clicks a link or takes some other action on the page, the portal processes the actionPerformed()method for the target portlet and the doView() methods for each portlet on the page. Then, it aggregates the results and sends the entire HTML document down to the browser.

While caching can reduce a lot of the overhead, there is still a lot going on. You could use Ajax to handle many of the user interaction events in the background, and then to update portions of the page, without requiring a full portal refresh cycle. This technique can vastly improve the end-user experience by increasing the responsiveness of individual actions, and the overall application performance. In certain circumstances, using Ajax can contribute to a cleaner overall architecture of your application. Having a secondary Ajax controller (such as a servlet or Web service) forces a stronger separation of your model code.

When applying a full Ajax controller design to your application, you should let the Ajax controller handle all basic user input actions and segmented display updates. Only use the portal actionPerformed() method for page-level transitions or to process major state changes.


Why Ajax and WebSphere Portal are not a good fit

So, why would you not want to use this new fangled paradigm in rich internet applications? All the weekly technical magazines insist that this is the way to go, and besides, your boss told you to use it because it's "one of our business goals." OK, we won't tell you not to use it, but we do want you to know about some potential pitfalls:

  • Using multiple controllers (for example a portlet, a servlet, and a Web service) adds to the complexity of the application.
  • Using Ajax forces a lot of logic to be processed on the client.
  • JavaScript can be difficult to debug, especially in a cross-browser environment.
  • Accessibility issues and mobile devices can force you to have redundant code. Because many screen readers and other assistive devices do not support JavaScript/Ajax, you need to provide alternate functionality.
  • Your application might not require extra data updates to the browser between pages.

So with all that said, you might decide that Ajax isn't for you and you will find another article to read. Wait, that's no fun. Read on, my friend, this stuff is way too cool not to add to your applications.

The bottom line is to take it slow. Find an application that could use a little kick, and add a dash of Ajax to a user form or wizard. Once you get your feet wet and understand how a little effort can produce some effective user enhancements, you will be ready to really add some magic to your portal applications.


Design considerations

When you add Ajax to a portal application, you are effectively adding multiple controllers to the classic MVC pattern. This decision has the potential benefit of forcing a cleaner separation of the model logic. The downsides are the added complexity and the unavoidable requirement to break the controller apart into these three aspects:

  1. The portlet
  2. The servlet or Web service
  3. The JavaScript-based client

The basic premise of using Ajax in a portal application is the need for a separate controller. Under normal circumstances, you use a servlet to perform the communications with the Ajax client. You can either bundle the servlet with the portlet WAR file or include it as part of a stand-alone Web application.

Figure 1 shows potential Ajax server targets.

  • If you bundle the servlet with the portlet WAR file, then you can share session data between the servlet and the portlet. The servlet, portlet, and the model code are tightly coupled.
  • If you do not need this level of coupling and the data and logic to be processed by Ajax are not dependent on the portlet, then you can create a stand-alone servlet or Web service to promote reuse.
Figure 1. Ajax server target possibilities
Ajax server target possibilities

Ajax toolkits

One of the downsides to implementing Ajax is the difficulty in writing good cross-browser JavaScript. There are many JavaScript and DHTML toolkits that provide Ajax abstractions. In fact, there are too many to test to determine which one best fits your needs. As with all open source projects, there will likely be a shake-out over the next couple of years.

A few of the most promising and well-designed toolkits that we have used are: Dojo, Rico, and DWR (see Resources). DoJo is preferred because it has an advanced Aspect-like architecture. DWR, or Direct Web Rendering, provides an easy mechanism to reference host-based JavaBeans from the client Javascript. Because there are many other good ones available, you need to determine what works for you.


Adding Ajax to a portlet application

To implement Ajax in your portal application, you need to follow a few simple steps. The following discussion assumes that you are bundling your Ajax servlet with your portlet WAR file.

  1. Create and define the Ajax servlet.
  2. Define a JavaScript reference variable that points to the servlet.
  3. Load any external JavaScript files.
  4. Implement the Ajax framework.

Create and define the Ajax servlet

The process of bundling a servlet with your portlet WAR file is very straight forward; however, even seasoned portlet developers are not always sure of all the details. So, here are the complete and sordid details.

  1. Define the servlet in the web.xml file, as in Listing 1
  2. Include the servlet JAR file or classes.
Listing 1. Servlet mapping in the web.xml
<servlet>
  <servlet-name>MyAjaxServlet</servlet-name>
  <display-name>MyAjaxServlet</display-name>
  <description></description>
  <servlet-class>
    com.ibm.ajax.MyAjaxServlet
  </servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>MyAjaxServlet</servlet-name>
  <url-pattern>/Ajax</url-pattern>
</servlet-mapping>

Define a JavaScript reference to the servlet

You need to define the global reference (see Listing 2) in the JSP file so that you have access to the portlet request library. After the global variable is defined, any JavaScript included can safely use it to point to the servlet.

Listing 2. Global reference to the servlet.
<script type="text/javaScript">
  var PATH = "<%= request.getContextPath() %>";
  var Ajax_SERVLET = PATH + "/Ajax";
</script>

Load any external JavaScript files

As with any external resource to be added to a portlet page, you must encode the URL and set the base context, as in Listing 3.

Listing 3. Script to encode the URL and set the base context.
<script type="text/javascript"
  src="<%=renderResponse.encodeURL(
          renderRequest.getContextPath() + "/js/myajax.js?v1.1.2")%>" >
</script>

Tip: By using a string argument on the JavaScript parameter, you force the browser to perform a cache refresh on each load. If you have JavaScript that might change frequently, this refresh forces browsers not to used old cached code. This example uses a version ID (?v1.1.2), but any string will work.

Implement the Ajax framework

Making Ajax perform its magic consists of a few boilerplate actions. We give you the overview here. You will see the code description in a future, follow-up tutorial.

  1. Create a global XMLHttpRequest object variable. Because all communications are asynchronous, you must define a unique variable for each Ajax event.
  2. Define an event to trigger the process. Typically, you use a JavaScript event in an input tag. For example:<input onChange='eventHandlerFunction()' ... >
  3. Define a function to handle the event; specifically, implement these tasks:
    • Instantiate the XMLHttpRequest (xhr) object variable. Details of this are browser specific, which we will cover in the future tutorial.
    • Set the xhr callback function. xhr.onreadystatechange()
    • Set the servlet, type, and parameters. xhr.open(), xhr.setRequestHandler(), and xhr.send()
  4. Define a call-back function to process the communication states and the response data.
    • This function handles the various communication state changes, such as when the call starts, when a connection is established, and when the response has been received.
    • Processing of the response typically consists of parsing the returned XML (or other contents), and using this data to update the DOM tree.

Figure 2 shows how all the pieces fit together.

Figure 2. AJAX communications event model
AJAX communications event model

Portal specific concerns

There are several issues that you should be aware of when implementing Ajax in a portal application.

Global JavaScript variables

In general, avoid using global variables in JavaScript within a portal application because of the fact that the portal aggregates several portlets into a single page. Namespacing of global JavaScript variables (as in Listing 4) is a good practice because you guarantee unique variable names, even if the same portlet is deployed twice on the same page.

Listing 4. Namespacing JavaScript variables.
// Global XMLHttpRequest variable
var <portlet:namespace />xhrFieldsRequest;

If you use an Ajax toolkit, the abstraction layer will resolve any naming conflicts.

Using ID attributes

ID attributes are often used in Ajax to quickly update a portion of the page. Because ID attributes within any HTML tag are global to the DOM, you need to make sure they are unique. If you have duplicate ID attributes, then results are unpredictable but generally not what you want, and the problem can be maddening to track down.

To be safe, namespace all ID attributes, even though doing this can make your code difficult to read, as you can see in Listing 5.

Listing 5. Safely namespacing an ID attribute.
<h1 id="<portlet:namespace />header">Hello</h1>
<script type="text/javascript">
  var x = document.getElementByID
    ("<portlet:namespace/>header");
  x.innerHtml = "GOODBYE!";
</script>

State maintenance

One pitfall that you can easily fall into is the inherent lack of state management when using Ajax calls in a portal. There is nothing to stop the user from taking an action in a portlet that can cause a page refresh. You need to make sure that any Ajax activity can be restarted without any dependency on the previous state. While it is possible to use cookies or Ajax calls to a servlet to check and store state information, avoid a dependency on the page's state. Make all Ajax calls atomic.

Other state issues that can easily trip you up are the back button and bookmarked URLs. In general, avoid major state changes based on Ajax. Leave that to real portal actionPerformed() calls.

Sharing session data

When you bundle a servlet with your portal application, you can share session data between the servlet and portlet. Typically, you want to use Application scope when sharing session data. To the servlet, this is the normal Session scope. To access Portlet scope variables from the servlet requires a special namespaced name value that is based on the portlet's ID that was set when it was originally deployed into a portal. It is very difficult to extract this value during development. Although mostly academic, the syntax of the Portlet scope variables is:

javax.portlet.p.<ID>?<NAME>

Where:

<ID> is the unique identification for the portlet

<NAME> name used to set the object in the Portlet session

Action URLs

Action URLs can be very tricky to deal with when using Ajax. In general, you should not attempt to store Action URLs in the shared session, because they are only valid for the current doView(). Attempting to use an ActionURL that was stored in the session from a previous doView() cycle will cause unpredictable results.

An example of when you would want to store Action URLs into the session is an Ajax-driven paging data table that contains Action URL links as part of the data set. When the user clicks Next, the browser generates an Ajax call to the servlet. Then, the servlet extracts the next page of data from the session, and it must have predefined Action URLs. Just be sure that anytime a doView() call is processed that any session data holding any Action URLs is regenerated.

Activity notification

Portal pages are often very busy, with a lot of aggregated information stuffed onto a single page. Because Ajax calls are performed in the background and they do not trigger the activity icon on the browser, you need to provide a consistent, visual mechanism to inform the user that something is going on. Otherwise, they can get confused and not know that the application is busy processing some action. (We surely don't want confused users.)

You could implement this notification using a floating DIV section display during activity, or using a simple message on the browser's status bar (although this is considered bad form by some). You could also integrate a custom theme extension that would display a common Please Wait message for any Ajax-enabled portlet on the page.


Conclusion

In this article, we described how and why you would use Ajax in your portal applications. In a future related tutorial, we will show you how to put all the pieces together to produce an Ajax-enabled database administration tool. Stay tuned.

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=143417
ArticleTitle=Using Ajax with WebSphere Portal
publish-date=06282006