Skip to main content

Creating RESTful IBM Lotus Domino applications in a Web 2.0 world with Project Zero

Raj Balasubramanian, Consulting IT Architect, Lotus
Raj Balasubramanian is a Consulting IT Architect for IBM Software Group. He works on customer engagements delivering application and infrastructure related projects. His interests range from anything technical to history and physics. During his copious spare time, he enjoys dating his wife and talking about robots with his sons. You can read about his technical and personal escapades on his personal blog Gurukulam.
Van Staub (van_staub@us.ibm.com), Staff Software Engineer, IBM
Van Staub works for IBM as the technical team lead for the IBM Lotus Domino Portal Integration team. Primarily, Van and his team integrate the following IBM products: IBM Lotus Sametime, IBM Lotus Domino, IBM Lotus Quickplace, IBM Lotus Quickr, and IBM WebSphere Portal. In his free time, Van enjoys fishing, traveling, and spending time with his wife and two dogs. For more information on Van and his interests, you can find related content on his developerWorks blog and developerWorks space.

Summary:  Learn how to create RESTful IBM Lotus Domino Web applications using Project Zero to deliver a responsive Web 2.0 application. This article explores the various options developers have to create RESTful Lotus Domino Web applications and shows how you can deliver such applications with the help of Project Zero.

Date:  11 Mar 2008
Level:  Intermediate
Activity:  13286 views

Creating IBM Lotus Domino applications using Project Zero allows developers to create exciting, responsive, dynamic applications in the Web 2.0 style with ease. Rather than creating applications from scratch, developers can leverage Project Zero's feature-rich APIs to quickly develop and deploy Lotus Domino applications with a Web 2.0 look and feel. This article walks you through the basic pattern a Lotus Domino developer can use to create REST-enabled Web applications. In doing so, we also point out the features of Project Zero that allow developers to concentrate on the Lotus Domino interaction rather than the overhead associated with Web programming.

REST

Representational State Transfer (REST) is a style of software architecture for building a distributed system, which the Web itself embodies. The recent buzz around Web 2.0 and the complexity of existing Web services standards have allowed the reemergence of REST as a viable style for building Web services. The REST approach in designing distributed systems lets you leverage most of what HTTP offers in building the application.

REST can be distilled to few key tenets:

  • Resource. Anything of importance is a resource and should be given that status. The key idea of a resource is that of addressability, using URL/URI.
  • Uniform operations and methods. HTTP introduces four primary methods, and REST-based services leverage these methods to expose the functionality of the services. For example, an operation to view a resource is implemented using the GET method of the HTTP interface. Details of the methods are covered later in this article.
  • Headers. HTTP headers carry meta-information such as authentication information, response code and error messages from the server, the content type of the resource being served by the server, and more. Some of the key headers used to address nonfunctional requirements are covered later as well. As the number of layers increases in any application development project, the number of artifacts produced and the management of the systems that support the application also increase. In a typical Service-Oriented Architecture (SOA) deployment, a number of layers are introduced to facilitate the separation of concerns and to assist in loose coupling.
  • Flexible representation. HTTP can provide a variety of uses for the resource based on what the client or consumer can use. A variety of MIME types are defined that can be used to deliver a resource in XML, JSON, or HTML format. Better yet, the client can specify which formats it can accept.

About the Lotus Domino application

We extend the Project Zero Employees demo to demonstrate REST-like interfaces using a Lotus Domino Employees application, based on the IBM Lotus Domino Directory template. Versions 7.0x and above of Lotus domino are supported. The Lotus Domino Directory contains users and groups with various views to expose details about persons and groups within the organization. Although the Lotus Domino Employees application is relatively simple, the concepts elaborated here can be applied to any Lotus Domino application. By using an existing Project Zero example, we concentrate on integrating a Lotus Domino server within the Project Zero programming model. The application was created with the M3 candidate for Project Zero and tested with Firefox 2.0.


About Project Zero

Before detailing the Lotus Domino Employees application, let's briefly outline Project Zero. As the Project Zero Web site states, Project Zero is "an agile development and execution environment which leverages REST and scripting runtimes to speed and simplify development and deployment of dynamic Web applications." Project Zero and its complement of Eclipse plug-ins allow developers to quickly assemble, build, test, and deploy REST-based applications.


REST-enabling Lotus Domino using Project Zero

Most Lotus Domino developers are familiar with Lotus Domino agents written in various languages, most notably LotusScript. Ultimately, a RESTful application, which exhibits the REST tenets previously mentioned, is accessible over the Web. Moreover, the application can be addressed through named resources. The instantiation of an application using a convention such as LotusScript or simple agents digresses from the cornerstone of REST, named resources.

Consider that Lotus Domino agents are invoked over the Web using a URL similar to http://domino.ibm.com/database.nsf/AgentName?OpenAgent as shown in figure 1. This is hardly the familiar named resource we want to achieve, and any information may be passed as arguments. This implementation or an equivalent servlet implementation is synonymous with a verb-based implementation rather than the RESTful characteristics. For example, the agent or servlet may receive parameters such as ?action=create&user=vstaub; a RESTful approach, on the other hand, simply operates on data within a POST method.


Figure 1. A Lotus Domino agent's named resource
A Lotus Domino agent’s named resource

A more appropriate implementation may be a Lotus Domino Security API (DSAPI) filter. DSAPI filters reside in the Lotus Domino HTTP stack and can be invoked when a condition is met within the URL. If you are familiar with IBM Lotus Quickr, all URLs containing /quickr are handled by the Lotus Quickr server's DSAPI filter. Using a DSAPI filter, the implementation is in effect embedded within the Lotus Domino server's HTTP stack. Unfortunately, creating a DSAPI filter is a daunting task for many because it requires an understanding of both the DSAPI toolkit and the C programming language. If a RESTful application is to facilitate a /database/document_unid or /database/view_name named resource convention, it can operate seamlessly with the existing Lotus Domino Web server invoking RESTful operations under predefined conditions. See figure 2. Depending on the reader's background, this implementation may be too technical or more time-consuming to implement.


Figure 2. A Lotus Domino DSAPI filter's named resource
A Lotus Domino DSAPI filter’s named resource

Finally, consider the Java language. Since Lotus Domino 6, you have been able to use Java to access Lotus Domino resources such as databases, views, or documents from a Java-enabled application. Couple the Java access with a servlet facilitating Web requests, and you have a viable solution to interact with Lotus Domino resources over the Internet. As previously stated, though, the servlet implementation is not purely RESTful. The Web-enabled, RESTful ability of an application is greatly improved by using an increasingly popular incubator project known as Project Zero.


Figure 3. A Project Zero application's named resource
A Project Zero application’s named resource

Identifying resources

Within a Lotus Domino Directory, we can identify the following resources:

  • Employee. Individual record about the person (equivalent to a Lotus Notes document).
  • Employees. A collection of employees (equivalent to a Lotus Notes document collection or a Lotus Notes view).

Another important aspect of identifying the resource is to understand how it is addressable. Employees are accessible as part of the default endpoint: http://[hostname]/employees.

An employee is accessible using a unique identifier such as a short name or email address: http://[hostname]/employees/[uid].


Resource representation

The exchange of data between the Lotus Domino Employees application and the client or browser is done using JavaScript Object Notation (JSON). The decision to use JSON arises from existing Project Zero support and its provision of a lightweight, easy-to-use data format within a JavaScript application. Ultimately, JSON is used to represent data, and a user within the Lotus Domino Directory can appear as the JSON object shown in listing 1.


Listing 1. JSON representation of an employee
{
      "FirstName": "Van",
      "FullName": "CN=Van Staub\/O=IBM",
      "HTTPPassword": "(355E98E7C7B59BD810ED845AD0FD2FC4)",
      "InternetAddress": "vstaub@ibm.com",
      "LastName": "Staub",
      "OfficeCity": "Atlanta",
      "OfficePhoneNumber": "(123) 456-7890",
      "OfficeState": "Ga",
      "OfficeStreetAddress": "4111 Northside Pkwy",
      "ShortName": "vstaub"
}

As you see later in the article, the ability to use this data within the JavaScript client is immediate. A JavaScript client application receives the JSON as an object, whereby values are referenced using a dot notation syntax. For example, to access the user's last name, use the syntax object.LastName. This syntax alleviates any parsing requirements and facilitates direct access to the data. For more information on JSON, refer to the JSON Web site.


Mapping methods

Table 1 illustrates the HTTP method used for realizing each of the use cases.


Table 1. Use case HTTP method types
Use caseResourceHTTP method
View employees EmployeesGET
View employeeEmployee GET
Create employee EmployeePOST
Update employeeEmployee PUT
Delete employee EmployeeDELETE

Response codes

Table 2 details the HTTP response for the operation and the service response in case of error. Any successful request gets a 200 OK response for GET, POST, PUT, and DELETE and 201 for POST, but the error condition triggers the appropriate HTTP response.


Table 2. Use case HTTP codes
Use case Failures
View employees401 (not authorized)
404 (when the employees can't be found)
View employee 401 (not authorized)
404 (when the UID can't be found)
Create employee401 (not authorized)
303 (if the given UID already exists)
Update employee401 (not authorized)
403 (forbidden)
Delete employee401 (not authorized)
403 (forbidden)

Designing using Project Zero

Project Zero allows developers to quickly create Web-enabled applications, focusing on REST. In short, the combination of a little Java programming and Project Zero allows you to create and deploy a RESTful Lotus Domino application or service. The Lotus Domino Employees application uses the existing Project Zero Employees demo application for much of the client-side logic. This allows the reader to realize the versatility of Project Zero combined with new Lotus Domino-specific server-side logic.

Project Zero lets you focus on the core business logic of the application rather than handling incoming Web requests, parsing URLs, and handling various methods. You have two options for implementing Project Zero applications: PHP and Groovy. The Groovy implementation nicely complements the ability to access Lotus Domino resources using Java. Essentially, you can write Groovy applications that access the Lotus Domino resources directly by using Java within the Groovy code or by calling functions from an existing Java library. By choosing to implement in Groovy, you can utilize an Eclipse plug-in to facilitate application creation and testing. Again, this lets you easily complete the process of creation, deployment, and testing.

At the core of the RESTful Lotus Domino application and most Project Zero applications is a RESTful design. Project Zero lets you create a Groovy file, a handler, to serve as the named resource. The client can then pass a virtual named resource to the handler. For example, you create a handler script named employees.groovy. Through a URL, the user then accesses the named resource /employees. A request to /employees can then serve the entire contents of the directory to the client. A similar URL request is /employees/username. The username member is a virtual resource. The employees.groovy file allows access to the username value, which, in turn, the implementation details handle appropriately. Notice the correlation between the virtual named resource and the Groovy handler's file name. The implementation details of the handler mimic the REST architecture. The operations such as create, update, retrieve, and delete (CRUD) are facilitated through corresponding functions in the Groovy handler as shown in table 3.


Table 3. Defining the Groovy handlers
Method typeURLGroovy handler function
GET /employeesonList()
POST /employeesonCreate()
GET /employees/[uid]onRetrieve()
PUT /employees/[uid]onUpdate()
DELETE /employees/[uid]onDelete()

Even though much of the information we have discussed has focused on the server side, Project Zero also facilitates client-side application creation. The popular Ajax framework, Dojo, is packaged as an add-on library. Thus, you can create incoming service requests and rich Ajax-enabled Web applications.

If you decide to use Project Zero, you can work with an exciting, cutting-edge development application and architecture incorporating everything from Eclipse to the much publicized Web 2.0.

Additionally, Project Zero offers implicit conversion of objects into a JavaScript notation, JSON. We can easily provide the response to the client as a Java object, which is then automatically converted into the JSON representations. It is easy to exploit the convenience capabilities of the Project Zero platform.

The Lotus Domino Employees application is composed of a layered implementation strategy: a client application, the Project Zero application, a collection of Java classes, and finally the Lotus Domino server itself as shown in figure 4.


Figure 4. Lotus Domino employees application model
Lotus Domino employees application model

The client, either a JavaScript Web-enabled application or a custom service, connects to the Project Zero application. Project Zero is responsible for any interaction with the client regarding processing the incoming request, locating the named resource, and sending the appropriate response. Project Zero eliminates the overhead necessary to handle and process the incoming Web request. By using the inherent Project Zero functions that handle the CRUD operations, you are relieved of much of the coding normally involved in the Web server application.

The Java classes are responsible for interacting with the Lotus Domino server. In essence, the Java classes are the logic of the Lotus Domino Employees application, which is nothing more than a collection of helper functions. Such helpers can utilize the Lotus Domino Java API, the notes.jar archive, to interact with the data stored in the Lotus Domino Directory.

You could just as easily write code that allows the Groovy classes to interact with Lotus Domino, but we prefer separating the logic of the application as helper functions within the Java classes. Because the Java classes are loosely coupled with Project Zero, the application can be reused in other scenarios -- in a rich client or servlet, for example. Similarly, applications written in Java that access the Lotus Domino server may be easily incorporated into the Project Zero platform to provide a Web-enabled deliverable.


Application behavior

Let's consider the flow of operations of any Lotus Domino application using the strategy described previously. Assume that a client operation makes an asynchronous call to the Project Zero application. Project Zero does little more than receive the request and begin invoking the necessary Java code to facilitate the needed operation. The Java classes interact with data on the Lotus Domino server. The Java object can then be serialized and sent back to the requestor.

The Lotus Domino Employees application consists of several very simple interactions with Lotus Domino based on the incoming operation to a user:

  1. Retrieve information from the Person document.
  2. Delete the person document.
  3. Register a new user.
  4. Update the person document.

Table 4 details the Lotus Domino server behavior.


Table 4. Defining the Lotus Domino behavior
Method type URLGroovy handler functionLotus Domino behavior
GET/employeesonList()Retrieve information from the person document(s)
POST /employeesonCreate() Register a new user
GET /employees /[uid]onRetrieve()Retrieve information from the person document
PUT/employees/[uid]onUpdate()Update the person document
DELETE /employees/[uid]onDelete() Delete the person document

Leveraging Lotus Domino security

To address security concerns, we use an existing Domino mechanism, Multi-Server Single Sign On (SSO). After a user successfully authenticates with Lotus Domino over the Web, the Lotus Domino server issues an encrypted token in the form of a cookie to the browser. The value in the cookie can be used for authentication. In this manner, we reuse the encrypted token from the cookie to connect to Lotus Domino in the Project Zero application. This has a twofold effect of protecting access to the Project Zero Web application:

  • It ensures that only valid users can use the application (authentication).
  • It ensures that the user accessing Lotus Domino obtains only data for which he or she is approved (authorization).

Project Zero has recently enabled support for the new Lotus Domino LTPAToken. The incorporation of the LTPAToken value from the cookie lets you create a Lotus Notes session based on the identity of the user. Creation of the Lotus Notes session is the point from which all the interaction with Lotus Domino begins.

To take advantage of the LTPAToken, an administrator configures the server for SSO. This can be done in the IBM Lotus Domino Administrator or Lotus Notes client by creating a Web SSO Configuration document as shown in figure 5.


Figure 5. Creating the Lotus Domino Web SSO Configuration document
Creating the Lotus Domino Web SSO Configuration document

Next, configure the Lotus Domino server to use the Web SSO Configuration document in the Server document by updating the Session authentication method to Mutliple Servers (SSO) using the Web SSO configuration you just created. See figure 6.


Figure 6. Configuring Lotus Domino for SSO
Configuring Lotus Domino for SSO

Note that the LTPAToken generated by the Lotus Domino server is valid only for the DNS domain listed in the Web SSO Configuration document. Furthermore, the LTPAToken is passed only to servers accessed using the domain in the Web SSO Configuration document. Essentially, this means that you want to access the Lotus Domino Employees Web application using the same URL used to access the Lotus Domino server. Do not use local hostnames or IP addresses.

To obtain an LTPAToken, log into the Lotus Domino server as shown in figure 7.


Figure 7. Creating the LTPAToken in the browser
Creating the LTPAToken in the browser

Verify that you have an LTPAToken by entering the following URL in the browser's address bar:

javascript:alert(document.cookie)

See figure 8.


Figure 8. Confirming you have an LTPAToken
Confirming you have an LTPAToken

Using the Lotus Notes session object

All interaction with Lotus Domino using the Java classes derives from the session object. From the session object, the programmer can initiate powerful operations such as opening databases, sending console commands, retrieving Notes.ini name/value pairs, and registering new users. In the Lotus Domino Employees application, the session object is constructed using the LTPAToken passed into the application from the browser. This process allows the application to perform only operations allowable to the logged-in user.

It's worth mentioning the details behind obtaining the Lotus Notes session object. The object can vary in implementation depending on the development environment as well as the intention of an implemented application. The Lotus Domino Designer Programming Guide, Volume 3 Java CORBA Classes outlines the differences in attaining a Lotus Notes session object.

The Lotus Notes session object can be created in two formats: using Remote Procedure Call (RPC) or using Internet Inter-ORB Protocol (IIOP). RPC calls require the Lotus Notes client, IBM Lotus Domino Designer, or the Lotus Domino server to be installed local to the running application. The Lotus Domino Employees application, an example of this format, creates a local session to the running Lotus Domino server. This choice is intended to maximize performance to provide a responsive Web interface.

Configuring Project Zero for RPC sessions

To do any Lotus Notes Java programming, the applicable Lotus Notes Java library must be included in the class path of the project. When using RPC calls, include the notes.jar archive in your application's Java Build Path. When running your Project Zero application for the first time, you may receive the error shown in figure 9.


Figure 9. The Lotus Notes Java library is missing
The  Lotus Notes Java library is missing

Essentially, this error means that the native call to the nlsxbe library could not be found. To correct the error, you must add it to the java.library.path variable of the Project Zero application. The notes.jar library makes native calls to functions within the Lotus Domino program directory. Native functions, in turn, call other native functions. If you've done any previous Lotus Notes Java programming in Eclipse, you may be aware that the easiest solution is to add the Lotus Domino or Lotus Notes program directory to the system's PATH environment variable. In Project Zero, the requirements are slightly different. To resolve the preceding error, add the path to the Lotus Domino or Lotus Notes program directory in the runtime configuration of your Project Zero application as shown in figures 10 and 11.

Select the Arguments tab of the Run dialog box as shown in figure 10. Then in the VM arguments pane, append the path of the Lotus Domino or Lotus Notes installation to the java.library.path argument:

-Djava.library.path="${ZERO.NATIVES};C:/Lotus/Domino"

Remember to place a semicolon to separate any existing arguments from the newly added Lotus Domino or Lotus Notes installation path.


Figure 10. Configuring the Lotus Domino VM argument
Configuring the Lotus Domino VM argument

Select the Environment tab of the Run dialog box as shown in figure 11. Edit the PATH variable from the list, and in the Edit Environment Variable dialog box that appears, append the path of the Lotus Domino or Lotus Notes installation.

Again, remember to place a semicolon to separate any existing arguments from the newly added Lotus Domino or Lotus Notes installation path.


Figure 11. Configuring the Lotus Domino PATH variable value
Configuring the Lotus Domino PATH variable value

Creating an RPC session

Assuming the user has already authenticated to the Lotus Domino server, the Groovy files pass the LTPAToken to the Java SessionHelper class.

Session session= SessionHelper.getInstance()
.getSession(zget("/request/cookies/in").get("LtpaToken"));

The SessionHelper class, in turn, creates the Lotus Notes session object as shown in listing 2.


Listing 2. Creation of the Lotus Notes session object
// verify that the Zero HTTP thread has been properly
// initialized for Notes RPC communication
Long threadId= new Long(NotesThread.currentThread().getId());
		
System.out.println("Zero thread : " + threadId + " using LtpaToken : " + ltpaToken);
		
...
// already created the NotesThread?
if(sessions.containsKey(threadId)){
	// not really an error
	System.err.println("NotesThread already initialized");
} else {
	System.out.println("Initializing NotesThread");
		
	// initialize the NotesThread
	NotesThread.sinitThread();
}
			
// create a Notes Session
// use null to indicate an RPC connection to the
// server on which the Project Zero application runs
Session session= NotesFactory.createSession(null, ltpaToken);
		
System.out.println("Storing NotesSession for Zero thread : " + threadId);
		
// cache the session for future use
sessions.put(threadId, session);
		
System.out.println("NotesSession created for user " + session.getUserName());
		
return session;

...

When making RPC calls, the NotesThread object must be initialized prior to utilizing the session. This step is not required for IIOP implementation. You must also call the stermThread function at the end of processing to prevent any abnormal terminations from affecting the running Lotus Domino server. Once a session object is obtained, it can be used to interact with the Lotus Domino server using the access control level granted to the user defined by the LTPAToken.

Much of the time we invested on the project involved determining how to handle the Lotus NotesThread objects. The Project Zero application uses three separate threads by default to handle incoming HTTP requests in a round-robin fashion. Each of those requests must be properly initialized by the NotesThread class before proceeding to interact with Lotus Domino. Failure to do so normally results in the error shown in listing 3.


Listing 3. Improperly initialized NotesThread error
Caused by: java.lang.UnsatisfiedLinkError: NCreateSessionWithTokenOrName
	at lotus.domino.local.Session.NCreateSessionWithTokenOrName(Native Method)
	at lotus.domino.local.Session.createSessionWithTokenOrName(Unknown Source)
	at lotus.domino.NotesFactory.createSessionC(Unknown Source)
	at lotus.domino.NotesFactory.createSession(Unknown Source)
	at com.ibm.devworks.SessionHelper.createSession(SessionHelper.java:24)
	at com.ibm.devworks.SessionHelper.getSession(SessionHelper.java:60)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke
	(ReflectionMetaMethod.java:56)
	at org.codehaus.groovy.runtime.MetaClassHelper.doMethodInvoke
	(MetaClassHelper.java:599)
	at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1030)
	at org.codehaus.groovy.runtime.Invoker.invokeMethod(Invoker.java:69)
	at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:66)
	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN
	(ScriptBytecodeAdapter.java:165)
	at employees.onList(employees.groovy:23)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke
	(ReflectionMetaMethod

The UnsatisfiedLinkError indicates that the NotesThread was not properly initialized.

The HTTP threads, once initialized, must be properly disposed. Disposal is facilitated by the NotesThread.stermThread() function. Our intention is to initialize the Zero HTTP thread when the incoming request is received in Zero and subsequently dispose of the NotesThread prior to rendering the output. See listing 4.


Listing 4. Disposing the session object and NotesThread
def onList() {

		try {
			
			// create a Session from the SessionHelper
			// all Domino operations require a Session
			Session session= SessionHelper.getInstance()
				.getSession(zget("/request/cookies/in").get("LtpaToken"));
			
			...

		} catch (NotesException e) {

			request.status = HttpURLConnection.HTTP_INTERNAL_ERROR
	  		request.error.message = e.getMessage()
			request.view = "error"

		}
		
		// properly dispose of any Domino objects by using the
		// SessionHelper
		SessionHelper.getInstance().shutdown();
	    
		// finally render the content to the client
	    render()

 }

/**
	 * Properly dispose of any remaining Sessions or NotesThreads.
	 *
	 */
	public void shutdown(){
		
		System.out.println("Closing NotesSession ...");
		
		// get the Zero thread requesting Notes shutdown
		Long threadId= new Long(NotesThread.currentThread().getId());
		
		try {
		  Session session= (Session)sessions.get(threadId);
		
		  System.out.println("Closing NotesSession for user " + session.getUserName());
			
		  session.recycle();
			
		  System.out.println("NotesSession closed");
			
		} catch (NotesException e) {
			e.printStackTrace();
		} finally {
			
		  // terminate the NotesThread properly
		  NotesThread.stermThread();
			
		  // remove a the so a NotesThread can be initialized
		  // on the Zero thread
		  sessions.remove(threadId);
			
		  System.out.println("Removed NoteSession for Zero thread : " + threadId);

		}
	}

This model proved to be quite challenging. At times, NotesThreads were terminated properly while other requests caused JVM crashes. The crashes shown in listing 5 were seen during the course of programming.


Listing 5. JVM crash error contents
#
# An unexpected error has been detected by HotSpot Virtual Machine:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x60001457, pid=2660, tid=6448
#
# Java VM: Java HotSpot(TM) Client VM (1.5.0_12-b04 mixed mode)
# Problematic frame:
# C  [nnotes.dll+0x1457]
#

Such errors were attributed to initializing a NotesThread on an already initialized Zero HTTP thread or attempting to terminate a NotesThread on an initialized Zero HTTP thread. We faced a dilemma between properly initializing and disposing of NotesThreads and leaving the threads initialized, but resulting in a possibly unstable Lotus Domino server. We chose the latter for demonstration purposes for the article. There are ways to combat this design problem. You can extend the NotesThread class and encapsulate your logic within it. Once the run() or runNotes() method completes, the NotesThread disposes gracefully, but you may be required implement threads that complete very specific operations. The choice for design is an interesting one, and you can post questions on the Project Zero forums for assistance from the Project Zero team and others in the community.

The intent here is not to deter you from exploring Project Zero and Lotus Domino, but to inform you about our experience. There may be workarounds or known technical limitations for the issues described in the article.

Also note that the application creates a local Notes session, but it is not limited to accessing data on the local server or Lotus Notes client. You may update code to access databases on remote Lotus Domino servers by specifying the Lotus Domino server name in the getDatabase() function.

For more details, see the "Using the Lotus Domino Employees application" section found later in this article.

Creating an IIOP session

Although it is not implemented in the Lotus Domino Employees application, IIOP is an alternative to the RPC format. IIOP may be desirable when a Project Zero application is not running on a server with a local Lotus Domino server or Lotus Notes client installation. You trade the requirement of a local Lotus Domino or Lotus Notes installation for the need to run the DIIOP task on the Lotus Domino server. The DIIOP task facilitates the remote connections accessing databases, views, documents, and more.

RPC code may be updated as shown in listing 6 to facilitate IIOP connectivity to Lotus Domino.


Listing 6. IIOP connection code differs
private static Session createSession(String server, String token) {
System.out.println("Creating Session");

	try {
		// server should be a DNS address or IP		
		Session s = NotesFactory.createSession(server, token);

		System.out.println("Creation successful");

		return s;

	} catch (NotesException e) {
		System.err.println("Creation failed");

		e.printStackTrace();

		return null;
	}
}

Note that the only substantial change is the removal of NotesThread processing. When you use IIOP, the NotesThread session is no longer required.

IIOP introduces new configuration considerations on the Lotus Domino server: security, access to the file diiop_ior.txt on the Lotus Domino server, and various port configurations. You should also ensure that the "Allow HTTP clients to browse databases" option shown in figure 12 is selected on the Internet Protocols - HTTP tab of the Lotus Domino Server document.


Figure 12. Configuring DIIOP
Configuring DIIOP

This setting allows the session to obtain a list of databases on the server. For more information on DIIOP, consult the Lotus Domino Designer Programming Guide's NotesFactory section.


Accessing Lotus Domino data

Now that you have established the Lotus Domino Employees application's behavior, the helper functions, using the Notes session, begin querying or modifying the Lotus Domino directory. Because the focus of the Lotus Domino Employees application is specific to users, the helper functions operate on Lotus Domino Person documents.

For example, the request to the resource /employees retrieves all contacts from the directory. This action is equivalent to obtaining all documents that were created with the Person form in the database names.nsf. The code in listing 7 illustrates this behavior.


Listing 7. Obtaining all employees using Lotus Notes document collections
public Employees getAllPeople() {
		// conduct a search for people created with the Form People
		// this is true for all users
		DocumentCollection dc= searchNab("Form=\"Person\"");
		
		// convert the collection into Employees
		Employees contacts= getPeople(dc);
		
		// recycle the document collection
		try {
			dc.recycle();
		} catch (NotesException e) {
			e.printStackTrace();
		}
		
		return contacts;
	}


Notice that the getAllPeople function sends a search formula to the NAB to obtain all Person documents, which is identical to the search a client user may conduct on a Lotus Domino database. Rather than opening the directory and conducting a search, you can open the People view in the directory and return the DocumentCollection within it. This approach lets you better leverage existing Lotus Domino structures to reduce code and performance overhead. It also alleviates the requirement of a directory that is full-text indexed.

Lotus Domino data representation

In the previous retrieval to get all employees, the structure returned is a Notes object, DocumentCollection. DocumentCollection is named correctly; it consists of a collection of Document objects. The Document object corresponds to the actual Person document from the directory. To make the data representation process clear, we first copy the needed values from the document into a new Employee object as shown in listing 8.


Listing 8. Document to Employee object conversion
public Employee(Document doc){
data= new HashMap<String, String>();
		
	try {
		// verify that the document is a person doc
		if(doc != null &&
			doc.hasItem("Form") &&
			doc.getItemValueString("Form").
				equalsIgnoreCase("Person")){
					
			// pull data as Strings from the person doc
			for(int i= 0; i < Employee.FIELDS.length; i++){
				data.put(Employee.FIELDS[i], doc.getItemValueString(
							Employee.FIELDS[i]));
			}

			notesUrl= doc.getNotesURL();
			
}
	} catch (NotesException e) {
		e.printStackTrace();
		
		notesUrl= "";
	}
}

The code iterates over the predefined field names (shown in listing 9) specified in the Employee object, and it copies the value of the corresponding field in the Person document into a HashMap contained in the employee object.


Listing 9. Iterating the field names
public static final String NAME= "FullName";
public static final String UID= "ShortName";
public static final String FIRSTNAME= "FirstName";
public static final String LASTNAME= "LastName";
public static final String EMAIL= "InternetAddress";
public static final String PHONE= "OfficePhoneNumber";
public static final String PASSWORD= "HTTPPassword";
public static final String ADDRESS= "OfficeStreetAddress";
public static final String CITY= "OfficeCity";
public static final String STATE= "OfficeState";
public static final String ZIP= "OfficeState";

Essentially, we mimic the name/value pairs contained in the Document object within the Employee object. In a large-scale system, copying the actual data guards against the possibility of the Lotus Domino object being recycled or removed before the JSON conversion process begins, which can result in an error.


Converting Lotus Domino data to JSON

Consider the state of the application when an Employee object is populated with user data and subsequently needs to convert this to JSON and send the JSON to the client. This process occurs in the retrieval of a user using the request employees/[uid]. Once again, Project Zero makes this extremely easy as shown in listing 10.


Listing 10. Project Zero inherently has JSON conversion
// retrieve the Employees Collection by creating a
// NabHelper and requesting all the people
Employees employees= new NabHelper(session).getAllPeople();
				
if(employees != null){
	
// automatically serialize the object to JSON using
	// Project Zero's custom converter
	request.view='JSON'
	request.json.output= employees; 
}

render()

The key step in the preceding code is providing the actual object as the JSON output to the client. For simple objects, Project Zero automatically converts the object into JSON using the public get functions. For more complex objects, you should define the conversion process using a custom converter.

Converting Lotus Domino data using a custom converter

To do the conversion implicitly using the request.json.output = object syntax, we have created a custom converter. Given an object, Project Zero instantiates the appropriate custom converter to convert the object into JSON. To allow this, create a class that implements the IConverter (Milestone 1) or the Converter (Milestone 2) interface. Our class is provided in listing 11.


Listing 11. An employee customer converter
public class EmployeeConverter implements Converter {

	public Object toJson(Object o) {
		Employee person = (Employee) o;
		JSONObject json = new JSONObject();
		
		// the person document's fieldname value pairs have already been
		// stored as a hashmap when the document was originally read
		// simply convert the contents into JSON
		
		Iterator it= person.getData().
			keySet().iterator();

		while(it.hasNext()){
			String param= (String)it.next();
			json.put(param,
					(String)person.getData().get(param));
		}

		return json;
	}

...

The incoming object in the request.json.output assignment is provided as an argument in the toJson function. We then create a JSONObject to store the name/value pairs already stored in the Employee object. The JSONObject representation of a contact appears as shown in listing 12.


Listing 12. JSON representation of data within the Person document
{
      "FirstName": "Van",
      "FullName": "CN=Van Staub\/O=IBM",
      "HTTPPassword": "(355E98E7C7B59BD810ED845AD0FD2FC4)",
      "InternetAddress": "vstaub@ibm.com",
      "LastName": "Staub",
      "OfficeCity": "Atlanta",
      "OfficePhoneNumber": "(123) 456-7890",
      "OfficeState": "Ga",
      "OfficeStreetAddress": "4111 Northside Pkwy",
      "ShortName": "vstaub"
}

The JSONObject is not limited to name/value pairs. You can create complex objects using strings, numbers, values, arrays, and other objects. For example, listing 13 is a representation of databases on a Lotus Domino server. The JSONObject contains an array (JSONArray) of JSONObjects containing database information. Each object also contains an error status and error message.


Listing 13. A complex representation of Lotus Domino databases
{
   "databases": [      
      {
         "filename": "names.nsf",
         "filepath": "names.nsf",
         "httpurl": "http:\/\/domino.ibm.com\/__85257350001864E6.nsf?OpenDatabase",
         "message": "",
         "notesurl": "notes:\/\/Domino@IBM\/__85257350001864E6.nsf?OpenDatabase",
         "replicaid": "85257350001864E6",
         "status": 0,
         "template": "StdR4PublicAddressBook",
         "title": "IBM's Directory"
      }, 
      {
         "filename": "webadmin.nsf",
         "filepath": "webadmin.nsf",
         "httpurl": "http:\/\/domino.ibm.com\/__85257350001883E1.nsf?OpenDatabase",
         "message": "",
         "notesurl": "notes:\/\/Domino@IBM\/__85257350001883E1.nsf?OpenDatabase",
         "replicaid": "85257350001883E1",
         "status": 0,
         "template": "",
         "title": "Domino Web Administrator (7)"
      }
   ],
   "message": "",
   "status": 0
}

Configuring a custom converter

Now that you have implemented a custom converter, you need to connect the object and the converter. You do this by updating the Project Zero's configuration file, zero.config. To connect a converter with an object, use the following syntax:

[/config/json/converters/object=convert_class

For example, to connect the Employee object with the employee converter, use the following configuration:

/config/json/converters/com.ibm.devworks.Contact=com.ibm.devworks.json. EmployeeConverter

If you decide to implement converters for Lotus Notes classes themselves, be aware of the object's type returned. As stated earlier, you can create varying types of Sessions to access Lotus Domino data. Depending on the session's connection, the type of Lotus Domino data returned may be different. To ensure consistent behavior, you may want to set up the custom converters to encompass varying types of the same Lotus Domino resource. See listing 14.


Listing 14. Varying types of Lotus Domino objects requiring a single converter
config/json/converters/lotus.domino.Database=
com.lotus.rest.json.converters.DatabaseConverter
config/json/converters/lotus.domino.local.Database=
com.lotus.rest.json.converters.DatabaseConverter
config/json/converters/lotus.domino.cso.Database=
com.lotus.rest.json.converters.DatabaseConverter


Using the Lotus Domino Employees application

To use the Lotus Domino Employees application, you need to install Eclipse and the Project Zero plug-in on the Lotus Domino server. After they are installed, follow these steps to begin using the application:

  1. In Eclipse, choose File - Import - General - Existing Projects into Workspace, and then select the Select Archive File option.
  2. Click Browse to locate the employee.domino.demo.-all-1.0.zip file, and then click OK.
  3. Click Finish to import the selected project.
  4. Create a new Runtime Configuration by choosing Run - Run As - Project Zero Application. After you have started, stop the application using the Stop icon on the console view.
  5. Edit the Runtime Configuration by choosing Run - Run - Project Zero Application - employee.domino.demo. Edit the java.library.path and PATH variables found on the Arguments and Environment tabs, respectively, and referenced in the "Configuring Project Zero for RPC Sessions" section of this article. Click Apply, and then close.
  6. Open the config/zero.config file.
  7. Update the settings in config/domino/rest stanzas to work with your Lotus Domino server. See the code in listing 15.


    Listing 15. Configuring the Lotus Domino Employees application
    # mail directory of the Domino server relative
    # to the data directory
    # during contact creation a mail file is also created
    
    /config/domino/rest/mailDirectory = "mail"
    
    
    # field that uniquely identifies people
    # this should conform to the value passed using REST
    # for example, /employees/[uid] is /employees/vstaub
    
    /config/domino/rest/employeeSearchField = "ShortName"
    
    
    # certifier ID password
    
    /config/domino/rest/certIdPassword = "password"
    

  8. Again, choose Run - Run As - Project Zero Application. A message such as "C:/Eclipse_ProjectZero/Workspace/employee.domino.demo running on port 8080" appears when the application is running.
  9. Request a Lotus Domino protected resource such as names.nsf.
  10. Log in to the Lotus Domino server.
  11. Request http://<domino_server_fqdn>:8080.
  12. Click List Employees to begin.

Note that names.nsf must be full text indexed. You can accomplish this from the Properties box of the names.nsf database using a Lotus Notes client. The Firefox client has also yielded the most stable client-side use of the Dojo widgets. If everything is successful, you see the Lotus Domino Employee application shown in figure 13 in your browser.


Figure 13. A successful deployment of the Lotus Domino Employees application

Logging has been implemented as System.out and System.err statements. If problems occur, consult the console log for information.


General tips

Use Eclipse debugging. Review the Global Context parameters variables when debugging for helpful information about the running application. Using the debugging perspective confirmed our suspicion that several threads were used to facilitate HTTP requests with each thread requiring Lotus Notes initialization.

Consult the documentation. Changes to Milestone 1 to Milestone 3 require the porting of older code. Know the version you have installed and the version of any examples you are consulting.

Start with an example. Try new features or integration by starting with a working example from the Project Zero team.

Test the code in a separate application. Bugs may be a factor of JVM or Project Zero nuances, not necessarily your code. This approach helps you understand the problem and possibly adapt to work with Project Zero.


Next steps

The concepts demonstrated in this article have a specific use case; however, the underlying model is one of Lotus Domino resource modeling using Project Zero. You can thus represent all Lotus Domino data using JSON and greatly enhance the usability of an existing application. Some general ideas may be to write an Ajax-friendly IBM Lotus Domino Web Access page that automatically retrieves the user's mail file and displays it dynamically on the page. Another idea is to create more responsive listings of Lotus Domino views and documents within an IBM Websphere Portal environment. It's amazing how easily Project Zero facilitates putting a new Web 2.0 spin on existing Lotus Domino concepts.


Conclusion

In summary, we have taken a simple Lotus Domino database and transformed it into a functional RESTful application by leveraging Project Zero. As we saw earlier, the use of scripting language such as Groovy along with the Project Zero framework greatly enhanced the development process. Finally, we see the result of a REST-based Domino application. Due to the popularity of REST and Web 2.0 concepts, any Lotus Domino developer can leverage the established concepts of designing and implementing RESTful Domino application using Project Zero. In doing so, you can expand the usage of any Lotus Domino application in new and exciting ways.



Download

NameSizeDownload method
employee.domino.demo-all-1.0.zip9879KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

Discuss

About the authors

Raj Balasubramanian is a Consulting IT Architect for IBM Software Group. He works on customer engagements delivering application and infrastructure related projects. His interests range from anything technical to history and physics. During his copious spare time, he enjoys dating his wife and talking about robots with his sons. You can read about his technical and personal escapades on his personal blog Gurukulam.

Van Staub works for IBM as the technical team lead for the IBM Lotus Domino Portal Integration team. Primarily, Van and his team integrate the following IBM products: IBM Lotus Sametime, IBM Lotus Domino, IBM Lotus Quickplace, IBM Lotus Quickr, and IBM WebSphere Portal. In his free time, Van enjoys fishing, traveling, and spending time with his wife and two dogs. For more information on Van and his interests, you can find related content on his developerWorks blog and developerWorks space.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus
ArticleID=292702
ArticleTitle=Creating RESTful IBM Lotus Domino applications in a Web 2.0 world with Project Zero
publish-date=03112008
author1-email=
author1-email-cc=
author2-email=van_staub@us.ibm.com
author2-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers