Many organizations have a wealth of information and data in existing IBM Lotus Domino applications that is needed by other applications. This article demonstrates how to develop a Java agent in IBM Lotus Domino Designer that runs on a Lotus Domino server. This agent uses the Java Messaging Systems (JMS) 1.1 API as well as the Java Naming and Directory Interface (JNDI) API to send messages to and receive messages from a JMS provider. This article uses IBM WebSphere MQ V6 as the messaging provider, but by using JMS 1.1, this code allows Lotus Domino applications to connect with any enterprise service bus (ESB) that supports JMS. (This code was tested with Lotus Domino V8, WebSphere MQ V6, and the JMS 1.1 APIs; however, this code should work with Lotus Domino V5 and later and JMS 1.0 and later.)
This article is written for the Lotus Domino programmer who wants to interoperate with messaging systems by capitalizing on the Java API support that Lotus Domino provides. It is assumed that you are familiar with the Java programming language as well as the Lotus Domino programming model.
Before we dive into the solution, let's get a high-level view of what we are trying to accomplish. Figure 1 is a Unified Modeling Language (UML) deployment diagram that provides some context for how this sample application works. As shown, this application involves two physically distinct servers: a Lotus Domino V8 server and a WebSphere MQ V6 server. You can certainly run the application co-located on the same server, but demonstrating the distributed network scenario provides a more likely solution. Additionally, figure 1 shows that the WebSphere MQ server offers the JNDI provider support as well as the JMS provider support without the need for additional software.
Figure 1. Architecture deployment diagram
Certainly, there are many ways to get data out of Lotus Domino and to other applications, so why use messaging and, more specifically, why use JMS? Messaging provides an asynchronous communication channel that enables Lotus Domino and any JMS provider to share data in a loosely coupled fashion (that is, without the producer or consumer having to know about each other). Additionally, by using the JMS APIs, this Java code allows Lotus Domino to interoperate with any JMS message provider as well as connect to a number of enterprise service buses.
The steps of this article are similar to the order in which you can construct this sample application. The steps and order are as follows:
-
Configure WebSphere MQ.
As this article is about connecting Lotus Domino to a JMS provider, you need to install and configure a JMS provider. We use WebSphere MQ V6 because of its support of JMS 1.1 and its popularity as Message Oriented Middleware (MOM). Because JMS requires a JNDI provider, we also use WebSphere MQ as the JNDI provider. This requires a supportPac, and then creating the JNDI administered objects that are bound to the MQ underlying entities. -
Configure Lotus Domino.
To demonstrate the Lotus Domino-to-JMS concept, we have developed a simple application with forms, views, and the Java agents. In this section, we cover the basics of the Lotus Notes application and discuss how to construct the Java agent in Lotus Domino Designer. Finally, we discuss the Java code and how it works. -
Run the samples.
To demonstrate the code, we run the agent to push messages to WebSphere MQ followed by showing the message as it appears in WebSphere MQ. Then we run a different agent that fetches the messages back from WebSphere MQ and into Lotus Domino to demonstrate that we can support the producer and consumer sides of messaging. Finally, we open the retrieved message in the Lotus Notes client as a Notes document showing the message body.
WebSphere MQ V6 supports JMS 1.1. This means that WebSphere MQ V6 can function as a JMS 1.1 provider. Remember that JMS is only a specification for an API; the messaging system provides messaging by implementing the JMS specification.
For JMS clients to connect to WebSphere MQ, you must create and configure a queue manager. A queue manager supplies the runtime processes that provide JMS capabilities to JMS clients. WebSphere MQ provides an Eclipse-based administration client to assist in this process.
- Start WebSphere MQ Explorer by choosing Start - All Programs - IBM Websphere MQ - Websphere MQ Explorer.
- Select the Queue Manager folder in the WebSphere MQ Explorer navigator, then right-click and select New - Queue Manager.
- In the wizard, enter Domino.QMGR as the queue manager name. Select "Make this the default queue manager" option. Enter SYSTEM.DEAD.LETTER.QUEUE in the Dead letter queue field. Leave the defaults for the other fields, and then click Finish as shown in figure 2.
Figure 2. Queue manager configuration
At this point, you have created a queue manager that is capable of storing messages in Websphere MQ, but JMS clients need a JNDI provider as well.
JNDI is only a specification, and thus it needs a provider to supply the implementation. IBM WebSphere MQ V6 can provide this implementation with the support of supportPac ME01, which in turn requires supportPac MS0B (see the "Resources" section). These supportPacs are easy to install: Unzip them, and copy the included JAR files to <MQ_Install>\Java\lib. Figure 3 shows the JARs that have been extracted and added to <MQ_Install>\Java\lib, namely, mqcontext.jar and com.ibm.mq.pcf-6.0.3.jar.
By using WebSphere MQ as our JNDI provider, there is no need for a separate JNDI provider that maps the JMS administered objects to the physical Websphere MQ queues – supportPac ME01 provides this capability.
Figure 3. JNDI supportPacs
The JMSAdmin tool is a command-line interactive tool that comes with WebSphere MQ that allows you to create JNDI administered objects in a JNDI provider (WebSphere MQ in this case). In order for the JMSAdmin tool to create JNDI objects in WebSphere MQ, you need to update the CLASSPATH to include the supportPacs. Open the batch script (C:\Program Files\IBM\Websphere MQ\Java\bin\JMSAdmin.bat) with a text editor, and add the JAR files to the CLASSPATH environment variable as shown in figure 4.
set CLASSPATH=%CLASSPATH%;C:\Program Files\IBM\Websphere MQ\Java\lib\mqcontext.jar;
C:\Program Files\IBM\Websphere MQ\Java\lib\com.ibm.mq.pcf.jar
Figure 4. JMSAdmin.bat CLASSPATH updates
After the JMSAdmin tool is updated with the supportPacs, you are ready to connect to your JNDI provider to create JMS administered objects. This is accomplished by setting the connection properties for the JMSAdmin tool in its configuration file (JMSAdmin.config).
# JNDI configuration settings in order to use WebSphere MQ as the JNDI provider
INITIAL_CONTEXT_FACTORY=com.ibm.mq.jms.context.WMQInitialContextFactory
PROVIDER_URL=localhost:1414/SYSTEM.DEF.SVRCONN
Because you run the JMSAdmin tool from the WebSphere MQ server, you set the PROVIDER_URL to localhost. As depicted in figure 1, the Lotus Domino Java agent connects remotely to the JNDI provider and thus uses the remote server's DNS name instead of localhost.
At this point, you can start the JMSAdmin tool from the command line:
C:\Program Files\IBM\Websphere MQ\Java\bin\JMSAdmin.bat
Creating JMS administered objects
The JMS specification uses a ConnectionFactory for creating JMS destinations (that is, queues and topics). Therefore, the first JNDI administered object you need to create is a ConnectionFactory. Use the following command inside the JMSAdmin interactive tool. (The JMSAdmin tool supports using a script instead of interactive mode, but for this article, we use the interactive interface.)
def cf(JMS_ConnectionFactory) qmgr(Domino.QMGR) tran(client) chan(SYSTEM.DEF.SVRCONN)
host(bpte-demo-8.austin.ibm.com) port(1414)
Table 1. Command breakdown
| Keyword | Description |
|---|---|
| def | Define – This defines new JNDI administered objects. |
| cf | ConnectionFactory – JMS 1.1 can use a ConnectionFactory for creating queue or topics. |
| qmgr | Queue Manager – This establishes where the ConnectionFactory locates its destination queues and topics. |
| tran | Transport – WebSphere MQ can use client or binding as a transport. In this article, we use client mode to allow a lightweight remote client. |
| chan | Channel – Clients must have a channel listening on the WebSphere MQ server that they can connect to access the queue manager and its resources. |
| host | Host – Because you are using client mode, specify the DNS name of the server hosting the queue manager. |
| port | Port – Because you are using client mode, specify the TCP/IP port that listens for connections. |
Then create the queue that holds the message as shown in figure 5.
def q(JMS_QUEUE) qmgr(Domino.QMGR)
This command creates a WebSphere MQ queue that is also saved as a JNDI administered object. Remember that this alias capability in JNDI is the ability to change the attributes of your underlying queue or topic without affecting the client code. In fact, you could move the queue to a completely different JMS provider without requiring the client code to be changed.
Figure 5. JNDI configuration
It's usually a good idea to verify that the command worked as you expected. In the JMSAdmin tool, simply run the following command:
display ctx
This command displays the JNDI context to which you have added.
At this point, your JMS provider is configured as well as your JNDI provider. Now you can move on to the JMS client code that connects to these providers to find the JMS destinations and to send messages to them. Also note that we didn’t have to create queues with WebSphere MQ Explorer; the queues and the JNDI entities were created at the same time through the JMSAdmin tool. See figure 6.
Figure 6. Queues in WebSphere MQ
Creating the Lotus Domino code
To demonstrate the concept, we created a simple Lotus Domino V8 application with Lotus Domino Designer V8. This application includes a simple form (see figure 7) for contact information and another form for holding the retrieved JMS messages. Similarly, we created two views to show the contacts and the retrieved messages, respectively. See the code JMSDemo.zip file in the "Download" section of this article.
Figure 7. Sample Lotus Domino application
Also included in the sample application are two Java agents: JMS_PUT and JMS_GET. Both agents are run from the Agent menu triggered by the user. (You may want a different triggering strategy; Lotus Domino provides many well-documented possibilities.) JMS_PUT sends messages to the JMS provider for all documents that are selected in the Employees view through the Lotus Notes client. The JMS_GET agent also is run from the Lotus Notes client, but it doesn’t require selecting any documents. This agent actually looks for messages on the JMS provider. For each message that it finds, it consumes the message and creates a Lotus Domino document with one field for the JMS message ID and another field for the JMS message body. This example uses the DxlExporter class provided by Lotus Domino to convert the employee document into an XML document. This is used as the JMS message body.
- To create the Java agent in Lotus Domino Designer, simply expand the Shared Code folder within the JMS Demo application.
- Select Agents in this folder to see the agents as well as a button for creating new agents.
- Click the New Agent button to create the Java agent (or open the existing code in the JMSDemo.zip file).
When you create a Java agent in Lotus Domino Designer, the IDE stubs out the skeleton for you as depicted in figure 8.
Figure 8. Stubbed Java agent
Before getting to the code, we need to add the JMS provider implementation classes and APIs to the agent. Recall that JMS is just a specification, and thus it provides a set of interfaces that JMS providers implement. Because we are using WebSphere MQ as the provider, we include the WebSphere MQ JAR files in our agent. With the Java agent opened as depicted in figure 9, click the Edit Project button to open the dialog box (figure 9) for adding JAR files to the agent. (In this article, we add the JARs to the agent for simplicity, but you will likely want to copy these JAR files to your Lotus Domino server and reference them in the server's Notes.ini file under the JavaUserClasses variable.)
Figure 9. Adding JARs to the Java agent
Table 2 describes each JAR file that is needed.
Table 2. WebSphere MQ JMS implementation JAR files
| File | Description |
|---|---|
| com.ibm.mqjms.jar | Provides MQ JMS implementation classes |
| com.ibm.mq.jar | Provides MQ implementation classes |
| com.ibm.mq.pcf.jar | Provides MQ classes for PCF |
| connector.jar | Provides J2EE connector API |
| dhbcore.jar | Needed by WebSphere MQ |
| fscontext.jar | Provides file system JNDI implementation |
| jms.jar | Provides the JMS interface classes |
| jndi.jar | Provides the JNDI interface classes |
| jta.jar | Provides the JTA implementation |
| mqcontext.jar | Provides the MQ JNDI implementation classes |
These JARs were copied from the WebSphere MQ installation directory in the C:\Program Files\IBM\Websphere MQ\Java\lib directory.
Let’s look at the code now and examine what each part does. Listing 1 shows the common code, which is code that is the same for the message provider and the message consumer. Notice the numbering of the code reflects that listing 2 and listing 3 follow the common code in listing 1.
Listing 1. Common code
1 lotus.domino.Session notesSession = getSession();
2 AgentContext agentContext = notesSession.getAgentContext();
3 Database db = agentContext.getCurrentDatabase();
4 Hashtable env = new Hashtable();
5 env.put(Context.INITIAL_CONTEXT_FACTORY,
”com.ibm.mq.jms.context.WMQInitialContextFactory”);
6 env.put(Context.PROVIDER_URL,
”bpte-demo-8.austin.ibm.com:1414/SYSTEM.DEF.SVRCONN”);
7 javax.naming.InitialContext ctx = new InitialContext( env );
8 javax.jms.ConnectionFactory qcf = (ConnectionFactory)
ctx.lookup("JMS_ConnectionFactory");
9 javax.jms.Connection jmsCon = qcf.createConnection();
10 jmsCon.start();
11 javax.jms.Session jmsSess =
jmsCon.createSession(true,javax.jms.Session.AUTO_ACKNOWLEDGE);
12 javax.jms.Destination jmsDest = (Destination) ctx.lookup("JMS_QUEUE");
|
Lines 1, 2, and 3 simply get a context to the Lotus Domino agent and database where the agent is running. Lines 4, 5, and 6 set up the JNDI properties to allow this agent code to connect to the JNDI provider, namely WebSphere MQ V6 running remotely. After the JNDI InitialContext is instantiated, you can use it to find the JMS ConnectionFactory as shown in line 8. This value must match the JMS administered object name that was created with the JMSAdmin tool. Then start the connection and create a JMS session. Now you are ready to find your JMS destination and start depositing messages or consuming messages. Line 12 shows us locating the JMS destination by looking for the JNDI name JMS_QUEUE. (This is created by the JMSAdmin tool above as shown in figure 6.)
Listing 2 shows the JMS producer code that demonstrates creating a JMS message and sending it remotely to the JMS provider. Because this agent runs against the documents that are selected in the view, line 16 gets a collection of these documents. Then we loop through the collection, converting each Lotus Domino document into an XML document that can be written as plain text in JMS (line 19).
Listing 2. Message producer
13 MessageProducer jmsProducer = jmsSess.createProducer(jmsDest);
14 TextMessage jmsMsg = jmsSess.createTextMessage();
// convert Domino document to an XML fragment
15 DxlExporter xmlGen = notesSession.createDxlExporter();
// get collection of selected documents from agent
16 DocumentCollection dc = agentContext.getUnprocessedDocuments();
17 Document doc = dc.getFirstDocument();
18 while (doc != null) {
// write document contents to JMS destination
19 jmsMsg.setText(xmlGen.exportDxl(doc));
20 jmsProducer.send(jmsMsg);
21 jmsSess.commit();
22 doc = dc.getNextDocument();
}
|
After running the agent, you can verify that the messages reached WebSphere MQ by using the WebSphere MQ Explorer. In the WebSphere MQ Explorer, select the Queues folder to see all queues on this queue manager, then right-click JMS_Queue and choose Browse Messages to see the messages in the queue.
This shows us a message for each document that was selected during our JMS_PUT agent run (see figure 10).
Figure 10. Messages in the queue
Double-clicking one of the messages displays the Properties dialog box that shows the message as it appears in WebSphere MQ (see figure 11).
Figure 11. The message in WebSphere MQ
At this point, you have successfully stored a complete Lotus Domino document as XML in a WebSphere MQ queue. And you have no WebSphere MQ-specific classes in your code, only JMS code that could just as easily send this message to WebSphere Enterprise Service Bus.
To demonstrate that you can also get messages from WebSphere MQ through JMS, we created another agent for consuming messages. Just like the producer code, this code doesn't know which JMS provider it is using – it simply knows how to talk JMS. Listing 3 shows the consumer code.
Listing 3. Message consumer
13 MessageConsumer jmsConsumer = jmsSess.createConsumer(jmsDest);
14 Message jmsIncoming = null;
15 do {
// The consumer will wait 1 second (1000 milliseconds) between polls
16 jmsIncoming = jmsConsumer.receive(1000);
17 if( jmsIncoming instanceof TextMessage ) {
18 System.out.println( "\n" + "Got message: "+((TextMessage) jmsIncoming).getText());
19 Document doc = db.createDocument();
20 doc.replaceItemValue("Form", "JMS_Imported");
21 doc.replaceItemValue("JMS_MsgID", jmsIncoming.getJMSMessageID());
22 doc.replaceItemValue("JMS_Message", ((TextMessage) jmsIncoming).getText());
23 doc.save(true, true);
24 }
25 jmsSess.commit();
26 } while ( jmsIncoming != null );
|
One big difference with the consumer code is that the consumer must wait and listen for messages as shown in line 16. When a message is received, we create a new Lotus Domino document for storing the JMS message to the Lotus Domino database (lines 19-23). For debugging purposes, we log the message to the Java console which we view by choosing Tools - Show Java Debug Console in Lotus Domino Designer as shown in figure 12.
Figure 12. Message logged to Java console
Additionally, opening the JMS_Imported view shows the documents that were created by running the JMS consumer code. Opening the document shows the XML text that was retrieved (see figure 13).
Figure 13. Messages stored as Domino documents
In this article, we set out to demonstrate how to send and receive messages from Lotus Domino to a JMS provider. This provides us an easy and inexpensive way to get Lotus Domino onto the bus (that is, an enterprise service bus). In this article, we demonstrated WebSphere MQ as the messaging provider, but the code works with any JMS provider.
Special thanks to Bob Balaban and Bobby Woolf for reviewing this article.
| Name | Size | Download method |
|---|---|---|
| JMSDemo.zip | 4.85MB | HTTP |
Information about download methods
Learn
-
Take the developerWorks tutorial, "Integrate Domino and WebSphere MQ."
-
Read the developerWorks article, "Running a standalone Java application on WebSphere MQ V6.0."
-
Read the developerWorks article, "JMS transport security, Part 1: Use WebSphere MQ to provide a secure JMS transport for WebSphere Application Server."
-
Learn more about ME01: WebSphere MQ – Initial Context Factory.
Get products and technologies
-
Download the ME01 supportPac.
Discuss





