Using Ajax to manipulate Lotus Notes documents

Giving users instant feedback instead of the time-consuming page reloads they're used to is simple when you use Ajax. Discover how a view and an agent can help you build Ajax-driven applications and learn how to define an API for getting the client and the Domino server to collaborate.

Joachim Dagerot (jd@dagerot.com), System Architect and Technical Lead, Strand Interconnect

Joachim Dagerot is a system architect and technical lead for Strand Interconnect. He has been involved in worldwide intranets that serve more than 130 million users. These days, he primarily focuses on Web development, with particular interest in accessibility and standard compliance. In his spare time, he develops Web services and blogs at domino.dagerot.com. You can reach Joachim at jd@dagerot.com.



07 June 2006 (First published 06 June 2006)

Also available in Chinese Russian Japanese

Everyone has used some kind of To Do list system. Such systems typically consist of small fragments of data that must be quick and easy to use. A To Do list is also a perfect example for demonstrating Asynchronous JavaScript and XML (Ajax) technology with Lotus Domino, and this article shows how you can use an Ajax design pattern to build a Lotus Notes application called ToDo-list that provides users with instant feedback and updates on their tasks.

This article guides you through the creation of the ToDo-List application, but also provides a download of the sample application to help you follow along. The application uses a Domino agent to process Ajax requests sent from a Web browser, such as creating and updating Notes documents, and a Domino view to generate XML used in the application. This article is intended for experienced Notes/Domino application developers with knowledge of JavaScript and XML.

To learn more about Ajax, refer to the Resources section of this article to find introductory articles.

The ToDo-list application maintains a record of To Do items, each of which contains Subject and Status fields. The Subject field holds information about what each item is (see figure 1); the Status field contains either a 0 for an outstanding action or a 1 for a completed action.

Figure 1. The Ajax-driven ToDo-list application
The Ajax-driven ToDo-list application

The power of Ajax-driven applications

Ajax-driven applications can increase the usability of any Web-based application, and a Lotus Domino server provides a good repository for rich-client applications because of added security and categorized views.

The design elements that Lotus Domino provides make developing Ajax solutions on the Domino platform simple. It is easy to build a session-aware (for security and personalization) Domino agent that handles your Ajax posts. In addition, you can configure a Domino view to provide HTML, XML, and even JavaScript Serialized Object Notation (JSON). Everything you need for a successful Ajax implementation is there.

Modern Web browsers and a mature Document Object Model (DOM) make it easier than ever to create rich applications for users. For example, we commonly include type-ahead or suggest fields in our projects in which users receive suggestions while they type to facilitate name lookups. In another project, we loaded a portal page with small boxes (that is, a <DIV>). Each <DIV> is populated from the backend with an Ajax call. Some of the boxes are updated automatically every 30 seconds, providing a manager with fresh information from the Enterprise Resource Planning (ERP) system.

A third example is another portal project in which each box header has a small "Add to my page" icon. When the user clicks that icon, a request goes in the background to the server with information about which box the user wants to subscribe to. The server responds with one of two messages: "The box is now on your personal page," or "You have that box already!"

In all these applications, we had to start by specifying an API. A badly specified API can ruin any project.


The API

Before you begin coding the ToDo-list application, you must decide how to format the information sent between the client and the server. Your system architects can choose whatever interchange format they want, but these days, it's typically XML, JSON, or simple text.

XML, JSON, or simple arguments

For two computers to communicate, you must set up a well-defined rule so that both the sender and the receiver know what to do with every piece of information. These rules can be complex, verbose, flexible, or simple and brief and easy to adopt.

If the choice of format is open, we recommend prioritizing human readability and integrity over smallness and overhead. Your format choices (summarized in Table 1) are:

  • XML. XML format is excellent for structured and well-defined data in which both the server and the client are completely aware of how the data will look. However, XML is a bit verbose, and older browsers' XML implementations have some quirks. Fortunately, those quirks do not affect the modern Ajax-driven example in this article.
  • HTML. HTML is excellent for sending data from the server to the Web browser for direct rendering, especially when compared with XML, where the client must first convert content to HTML before rendering it. HTML isn't recommended when the browser must analyze and react to the data.
  • JSON. JSON is both readable by humans and small without too much overhead. JSON is native for the JavaScript language, but needs additional coding on the Java server side.
  • CSV. Comma-Separated Value (CSV) is perhaps the most used and best proven method of exchanging data between two systems. Some even argue that it is human readable, although we don't subscribe to this view. It has no integrity check, but it has no overhead, either.
  • Text. Using pure text for information exchange is appropriate, for example, in value-pair combinations, such as a URL.

Table 1. Overview of different formats for information exchange

XML JSON HTML CSV Text
OverheadHeavyModerateHeavyVery lightModerate
Integrity checkVery goodVery lightNoneNoneNone
Human readableGoodModerateGoodImpossibleGood

For the examples in this article, you use text formats for requests to the backend system and XML in the responses. You need to put a bit of time and effort into defining the XML, too. It's not as easy as adding an extra field as you can in a pure Lotus Notes environment.


Defining the XML format

Using Lotus Domino's built-in XML generation

You can also use Lotus Domino's native XML format—Domino XML (DXL)—when requesting a complete document or design element. One advantage of doing so is that you can write considerably less code on the server side and use the built-in DXL generator, instead.

Later in this article, you define which methods the client can send to the server. But for now, you must decide which XML dialect to use to define one or many To Do items. Each To Do item in the ToDo-list application contains three values: key, subject, and status. The key is the Universal ID (UID) of the Lotus Notes document holding your To Do item. The subject is simply the task or action that the user wants to perform. The status is 0 for outstanding tasks and 1 for completed tasks.

In this example, the server responds to all calls with an updated item list. In a real situation, the response is more connected to the action that the server performed. The next step in this example is not only to send back the updated item list, but also to provide status information letting the client know what the server did as shown in the following code listing.

<response>
  <response status></response status>
  <document>
    <key></key>
    <subject></subject>
    <status></status>
  </document>
  <document>
    <key></key>
    <subject></subject>
    <status></status>
  </document>
</response>

Now, when the API, the exchange format, and the XML standard are set, you can start developing the server-side functions. After that, you can focus on the client-side code. However, before any of that can begin, you must decide which actions the server will perform on your documents.


Creating a client-to-server call

Each call generated on the client must contain an action argument so that the server knows what to do. Sometimes, it's also necessary to send extra arguments -- for example, if you want to toggle the status of an item. In such a case, the action is ToggleStatus, and the extra argument must contain information about which document to toggle the status on so that the Domino server can perform the correct action on the correct document.

All calls from the client are done using the HTTP GET method with some URL arguments. The following is an example of a complete URL that includes the method and key argument names.

http://host/ibm/ajaxdemo.nsf/AjaxHandler?open&method=deleteDocument&key=88877766fefe5678

What action should the server handle?

A Web page may use many different methods in your API -- for example, createDocument, updateDocument, deleteDocument, getDocument, and toggleStatus. Each method takes one or more arguments. The create, update, delete, and toggle status actions all change information in the database, and that change must be reflected in the To Do items list on the Web page. One way to reflect this change is to let the client perform an extra request to get the item list every time it makes a change in the database. A better solution is to set up the agent to return the updated To Do list each time the agent is called. (More about that later in this article.)

The server must react to the defined actions shown in table 2.

Table 2. Defined actions

Method Purpose Arguments Returns
CreateDocumentCreates a new Lotus Notes document and populates its fields with the data providedA list of fields; each field argument contains the field name, type, and valueAn XML object containing all items
UpdateDocumentRequests an update by providing a document identifier, the field name, and the value to be alteredDocument unique ID and a field argument; the field argument contains the field name and the new field valueAn XML object containing all items
DeleteDocumentDeletes a documentA unique ID of the document to deleteAn XML object containing all items
GetDocumentReturns the content of a documentA unique ID of the document to retrieveAn XML object containing the requested item
ToggleStatusToggles the status of a specific To Do itemA unique ID of the document whose status will be toggledAn XML object containing all items

These five actions are all you need to create a complete API between the Domino server and the Web browser. Now, let's move on to some server-side agent code.


Server side

The Domino server makes sure that all Ajax requests are treated in the proper way. Calls that manipulate data must be answered by some intelligence on the server side -- in this example, an agent. Calls that simply request information could easily rely on a Lotus Notes view, which can be an excellent XML source.

A view for listings

In this example, you use a Lotus Notes view configured to display XML. To avoid having Lotus Domino add its own HTML code, you configure the view to present its content as HTML.

In the ToDo-List application, you need only one column in this view to generate a complete XML node for each To Do item in the system. The first column, which lists the subject, is hidden and used only for setting up a sorting rule (see figure 2).

Figure 2. Lotus Domino Designer showing the XML view
Lotus Domino Designer showing the XML view

In addition to this view, you need a $$viewtemplate form that correlates to the view. This form contains the XML wrapping code in figure 3.

Figure 3. Part of the $$viewtemplate form
Part of the $$viewtemplate form

Presenting existing information is important, and the solution shown in figure 3 is perfectly suited for your needs. Now, you must create the Lotus Notes agent that will answer your requests.

A Domino agent for backend commands

W3C Recommendations

Remember that the World Wide Web Consortium (W3C) recommends using a POST method whenever data is changed in the backend and a GET method for all requests that do not change information on the server.

You know how to get data out of the Domino backend system in a fashion that suits an Ajax pattern, so how can you use a Domino agent to receive Ajax calls?

First, you must determine whether the agent should be called with the HTTP GET method or with a POST method. Because a To Do item contains so little information, you can use the GET method, which means that all arguments to the server are sent in the URL string as follows:

/database.nsf/ajaxHandlerAgent?openagent&method=UpdateDocument&key=FFF&status=0

The agent parses the arguments in the URL string and reacts based on the value in the method argument. This code listing shows how the ajaxHandlerAgent takes necessary actions depending upon the method argument.

UrlArguments args = new UrlArguments(); (1)
args.fromSession(session);

String method = args.getString("method"); if("ToggleStatus".equals(method)) { try { Document doc = thisDB.getDocumentByUNID(args.getString("key")); (2) String newStatus="1"; if(doc.hasItem("status")) { String currStatus = doc.getItemValueString("status"); if("1".equals(currStatus)) { newStatus=="0";} } doc.replaceItemValue("status",newStatus); pw.println("[" + "/" + thisDB.getFilePath() + "/XmlView?open]"); doc.save(true,false); } catch(Exception e) { pw.println(e);(3) } }

Note: The agent code fragment here only shows the ToggleStatus action. The full code for this agent as well as for the client are available for download from the Downloads section.

Pay particular attention to these lines in this listing: (1): The UrlArguments class is a small utility class that parses the URL arguments into a hashtable object. (2): In this line, the universalID argument of each Lotus Notes document comes into use. (3): The error handling in this line is insufficient in a production environment and should be revised as necessary.

Can you see the redirect that the agent is performing to send back the data in your view to the client?

Make the Domino agent serve a view

A huge advantage of using Ajax is that you can provide your users with instant, real-time information from the server. So, in your ToDo-list application, you send back a fresh list of items as a response to all server requests. You do this by letting the agent perform a server-side redirect to your XML view as shown in the next line of code. The Web browser then gets the content of the XML view as a response to all calls to the agent.

pw.println("[" + "/" + thisDB.getFilePath() + "/XmlView?open]");


The client side

On the browser, you need a function to create an Ajax request, placeholders for response information, and one or more hotspots with which the user can interact. Interaction points can be any object that can fire an event. The best known types are input type buttons and anchor links (see figure 4). If your users are familiar with categorized views, then you know what an interaction point can look like. Ajax makes this implementation even better: By loading only one category when a user expands a view, you can save a lot of overhead and provide a benefit to your users.

Figure 4. Interaction points in the ToDo-list application
Interaction points in the ToDo-list application

In figure 4, all available hotspots are highlighted in pink. The HTML for the various hotspots differs. The REFRESH! and the Create new todo! links are static code, while the link for the status symbol (the red X and the green checkmark) and item subject must be rendered on-the-fly. In this application, you set up a helper function, and this routine relies on the icons that the Domino server provides. No matter what HTML and JavaScript code is needed for generating a visual response to the user, the request to the server is set up in the same way using the XMLHttpRequest object.

Setting up and handling the Ajax request

Creating the actual XMLHttpRequest object is fairly easy. In more complex solutions, some kind of queue handler could be of interest. But for now, you can use the code shown in this code listing.

var xmlHttp;
function createXMLHttpRequest() { 
  if (window.ActiveXObject) { 
    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); 
  }
  else if (window.XMLHttpRequest) { 
    xmlHttp = new XMLHttpRequest(); 
  }
}

Creating, sending, and retrieving

For readability reasons, it's easier to map each method in the API to one method on the client side and a method with the same name on the server side. The JavaScript function shown in the next code listing is called every time the user clicks the status icon (the green checkmark or the red X). It starts by declaring a function (02) that is executed each time the xmlHttp object receives a change of state (12).

In line (10), the global variable Http is populated, and line (11) builds up the arguments that are added to the URL. In line (13), the Ajax object is initiated to be sent in line (16).

01  function toggleStatus(key) {
02    this.handleStateChange = function() {
03      if(xmlHttp.readyState == 4) {
04        if(xmlHttp.status == 200) {
05          refreshTodoList(xmlHttp.responseXML);
06        }
07      }
08    }
09
10  createXMLHttpRequest(); // build update string
11    var args='&method=ToggleStatus&key=' + key;
12    xmlHttp.onreadystatechange = this.handleStateChange;
13    xmlHttp.open("GET"
14      ,"./HandleAjaxRequests?open" + args
15      ,true);
16    SMLHTTP.send(null);
17  }

There are two checks before you take the response further to the XML parser at line (05).


Solutions for cross-server implementations

The XMLHttpRequest (also known as XHR) implementations today all have a security restriction that forbids the request to be handled by different domains, making it harder to use an Ajax solution when multiple servers are involved. We won't go into how or whether or not you can override this restriction. Instead, here are some alternative solutions that may need a bit more coding, but at least give users the same experience they get with the XMLHttpRequest implementation:

  • The iframe approach was the common way to get Ajax functionality before the XMLHttpRequest object was implemented everywhere. By loading content in a hidden iframe object and processing it in the background, you have more or less the same possibilities as with the XHR solution.
  • The proxy approach is the best and probably most common solution today when XHR is calling a non-origin server. In this approach, you must have a proxy on the server that serves the Ajax pages. The proxy then receives all Ajax calls and forwards them to the correct destinations.
  • The proxy design pattern also has possibilities for adding caching and some content validation, making it a good solution even when all content is loaded from the same server.

Wrapping it up

The Ajax design pattern is good for users because they receive a direct response to each action they perform. It's also good to have the server-side data complete in case of communication errors and the like. There are, however, a few things Domino developers or architects should consider before deploying Ajax solutions everywhere.

First, the XMLHttpRequest object isn't standard, even if there is a project from the W3C to create a standard from it. Another issue worth thinking about is server performance. An Ajax solution may not increase the bandwidth demands, but it will stress the Domino server in terms of number of transactions. And third, you may want to avoid building solutions that don't support Web browsers' Back button functionality.

Taking these negative points into consideration together with the user experience that a well-designed Ajax-driven solution provides, we think you can use Ajax wherever it can improve usability. This article has shown how easy it is to give your users that little extra element, making their Web experience much more convenient than typical page-oriented Web sites.


Download

DescriptionNameSize
Sample AJAX-driven ToDo-list applicationAjaxDemo_part1.nsf384 KB

Resources

Learn

Get products and technologies

Discuss

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 IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus
ArticleID=125634
ArticleTitle=Using Ajax to manipulate Lotus Notes documents
publish-date=06072006