ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Using OpenJMS withTomcat

by Jim Alateras
12/12/2001

This article illustrates how to integrate OpenJMS with Jakarta Tomcat. It deals exclusively with Tomcat v4 (or Catalina), which is the next-generation servlet/JSP container, and OpenJMS v.0.7.

The article assumes that the reader is familiar with both OpenJMS and Tomcat and does not describe how to install or use either product. Therefore, to allow you to work through this note we recommend that you install and familiarize yourself with the products by visiting their respective web sites.

The examples in this article have been tested with:

Figure 1 illustrates the relationship between the various Tomcat and OpenJMS components. The OpenJMS Web Application consists of JMS client code talking to the OpenJMS Client Library. The application is deployed within the Tomcat container. In this configuration, the OpenJMS server is executing outside the Tomcat container, and may even be executing on another machine on a different network.

Diagram.
Figure 1.

The user can access the OpenJMS application by entering the corresponding URL in the browser or application. Tomcat will resolve the URL and redirect it to the corresponding servlet, which will execute and then return a response back to the user. In the example that follows, Tomcat is used to serve both dynamic and static Web pages, therefore functioning as a typical Web server in addition to a servlet and JSP container.

Writing an OpenJMS Web Application

This section describes how to write and package a trivial OpenJMS Web application, which simply connects to the OpenJMS Server and publishes messages. The interaction diagram, shown in Figure 2, depicts the sequence of events between the various components.

Diagram.
Figure 2.

The table below provides a brief description of each of the components in the interaction diagram. Further details are provided in subsequent sections.

Component Description
Browser Represents the client browser making the requests to Tomcat.
Tomcat Container The Servlet/JSP container
SimplePublisher.html A static HTML page containing a form, which gathers information to publish messages to the OpenJMS Server
SimplePublisher.class A servlet class that interacts with the OpenJMS server
JNDI Provider Used to bind and lookup OpenJMS connection factories
OpenJMS Server A JMS-v1.0.2-compliant server

The sequence of events is as follows.

  1. The user will enter a URL to access the SimplePublisher.html page

    .
  2. Once the page is displayed in the browser, the user will complete the url, topic, and count fields.

    Dialogue box.
    Figure 3.

    Field Description
    url This denotes the URL of the JNDI Server, which holds the OpenJMS ConnectionFactories. The ConnectionFactories are used to bootstrap a connection to the OpenJMS Server. The form of the URL depends on the configuration of the OpenJMS Server.
    topic This is the name of the destination that messages will be published under. The messages are in the form publish message X, where X is the message number.
    count The number of messages to publish.
  3. 3. When the user presses the Submit Query button, the information in the form will be sent across to Tomcat and used to invoke the SimplePublisher servlet.

    The servlet will connect to the OpenJMS server, create a TopicPublisher using the topic form parameter, publish count messages, and then close the connection. On successful completion, the user should see the following response in their browser.

    Published 20 messages on topic jima to url rmi://localhost:1099/JndiServer.

The application itself is not useful, but it does provide all the information necessary to integrate the two components.

SimplePublisher.html

The HTML code includes the form, which gathers the user information and submits a request to the SimplePublisher servlet.

<html>
  <title>
    Simple Publisher
  </title>
  
  <body>
    <form method="get" action="../servlet/SimplePublisher">
      <table cols="2" cellspacing="10">
        <tr>
          <td>url</td>
          <td><input type="text" name="url" size="80"></td>
        </tr>            
      
        <tr>
          <td>topic</td>
          <td><input type="test" name="topic" size="30"></td>
        </tr>
      
        <tr>
          <td>count</td>
          <td><input type="text" name="count" size="5"></td>
        </tr>
      </table>
      <input type="submit">
    </form>
  </body>
</html>

SimplePublisher.java

Related Reading

Java Message ServiceJava Message Service
By Richard Monson-Haefel & David Chappell
Table of Contents
Index
Sample Chapter
Full Description
Read Online -- Safari

Below is the servlet code for this example. It uses the information passed across by the user to retrieve a ConnectionFactory from the JNDI provider, connect to the OpenJMS server, create a publisher, and publish messages to it. Finally, it closes the connection and returns a response to the user. If a problem is encountered while this request is being processed, a ServletException is returned to the user.

import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.jms.*;
import javax.naming.*;

public class SimplePublisher extends HttpServlet {
  public void doGet(HttpServletRequest request,
    HttpServletResponse response)
    throws IOException, ServletException {

    String url = request.getParameter("url");
    String topic_name = request.getParameter("topic");
    String count_str = request.getParameter("count");
    int count = 0;
    try {
      count = Integer.parseInt(count_str);
    } catch (Exception exception) {
      throw new ServletException("Error in converting count " + exception);
    }

    try {
      String factory_name = "JmsTopicConnectionFactory";
      Properties props = new Properties();

      if (url.startsWith("rmi")) {
        props.put(Context.INITIAL_CONTEXT_FACTORY,
             "org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory");
      } else {
        props.put(Context.INITIAL_CONTEXT_FACTORY,
             "org.exolab.jms.jndi.mipc.IpcJndiInitialContextFactory");
      }
      props.put(Context.PROVIDER_URL, url);
          
      // lookup the connection factory from the context
      Context context = new InitialContext(props);
      TopicConnectionFactory factory = (TopicConnectionFactory)
        context.lookup(factory_name);

      // if we can't find the factory then throw an exception
      if (factory != null) {
        TopicConnection connection = factory.createTopicConnection();
        TopicSession session = connection.createTopicSession(
       false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = session.createTopic(topic_name);

        if (topic != null) {
          TopicPublisher publisher = session.createPublisher(topic);
          if (publisher != null) {
            for (int index = 0; index < count; index++) {
              publisher.publish(session.createTextMessage(
                "publish message " + count));
            }
          }
        }

        // close the connction
        connection.close();
      }
    } catch (Exception exception) {
      exception.printStackTrace();
      throw new ServletException("Exception in processign request " + exception);
    }

    // formulate response
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head>");
    out.println("<title>OpenJMS Response</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("Published " + count + " messages on topic " + topic_name +
          " to url " + url + ".");
    out.println("</body>");
    out.println("</html>");
  }
}

Compiling and Packaging

To compile the servlet, you need the following libraries:

Library Description
openjms-client-0.7.jar The core OpenJMS client library
openjms-rmi-0.7.jar Additional classes for RMI-based OpenJMS server
exolabcore-0.3.1.jar Core Exolab library
jms_1.0.2a.jar Java Message Service (JMS) API

In addition, before we package the Web application, we must create the web.xml descriptor file, which identifies the servlet and its corresponding URL mapping.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
  PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>A Simple Publisher Application</display-name>
<context-param>
  <param-name>Webmaster</param-name>
  <param-value>jima@comware.com.au</param-value>
</context-param>
<servlet>
  <servlet-name>SimplePublisher</servlet-name>
  <servlet-class>SimplePublisher</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>SimplePublisher</servlet-name>
  <url-pattern>/openjms/*</url-pattern>
</servlet-mapping>
</web-app>

Finally, we must package all the above components in a Web Application Archive (war), which is identical, in format, to JAR files. The content of openjms.war, which is shown below, complies with the structure identified in the Servlet specifications.

     0 Wed Oct 03 16:18:36 GMT+11:00 2001 META-INF/
     0 Wed Oct 03 16:18:36 GMT+11:00 2001 WEB-INF/
     0 Wed Oct 03 16:18:36 GMT+11:00 2001 WEB-INF/classes/
     0 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/lib/
     0 Wed Oct 03 16:18:36 GMT+11:00 2001 servlets/
     0 Wed Oct 03 16:18:36 GMT+11:00 2001 build/
     0 Wed Oct 03 16:18:36 GMT+11:00 2001 dist/
   667 Wed Oct 03 16:18:36 GMT+11:00 2001 WEB-INF/web.xml
  3752 Wed Oct 03 16:18:36 GMT+11:00 2001 WEB-INF/classes/SimplePublisher.java
  4279 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/classes/SimplePublisher.class
268061 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/lib/openjms-client-0.7.jar
 44025 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/lib/openjms-rmi-0.7.jar
124524 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/lib/exolabcore-0.3.1.jar
 27724 Wed Oct 03 16:18:38 GMT+11:00 2001 WEB-INF/lib/jms_1.0.2a.jar
   757 Wed Oct 03 16:18:36 GMT+11:00 2001 servlets/SimplePublisher.html
    51 Wed Oct 03 16:18:36 GMT+11:00 2001 META-INF/MANIFEST.MF

The archive contains all the libraries, the servlet, and associated HTML files.

Deploying the OpenJMS Web Application

We must follow the following steps to deploy the archive, generated above, in Tomcat.

  1. Copy and unpack the archive in Tomcat's webapps directory.
  2. Modify Tomcat's server.xml file and add a new Context.
  3. Restart Tomcat.
  4. Start OpenJMS server.

Unpack the Web Application

Locate the webapps directory in your Tomcat installation, create the openjms subdirectory, and unpack the archive.

The directory structure should be similar to this:

webapps/openjms
webapps/openjms/META-INF
webapps/openjms/META-INF/MANIFEST.MF
webapps/openjms/WEB-INF
webapps/openjms/WEB-INF/classes
webapps/openjms/WEB-INF/classes/SimplePublisher.java
webapps/openjms/WEB-INF/classes/SimplePublisher.class
webapps/openjms/WEB-INF/lib
webapps/openjms/WEB-INF/lib/openjms-client-0.7.jar
webapps/openjms/WEB-INF/lib/openjms-rmi-0.7.jar
webapps/openjms/WEB-INF/lib/exolabcore-0.3.1.jar
webapps/openjms/WEB-INF/lib/jms_1.0.2a.jar
webapps/openjms/WEB-INF/web.xml
webapps/openjms/servlets
webapps/openjms/servlets/SimplePublisher.html
webapps/openjms/build
webapps/openjms/dist

Modify the server.xml Configuration File

In Tomcat's server configuration file, add a new context that defines the OpenJMS Web application. The configuration redirects URLs in the form of http://localhost:2222/openjms/ to the Web application we have just deployed.

:
:
:
<Server port="2220" shutdown="SHUTDOWN" debug="0">
  <Service name="Tomcat-Standalone">
    <!-- Define a non-SSL HTTP/1.1 Connector on port 8080 -->
    <Connector className="org.apache.catalina.connector.http.HttpConnector"
               port="2222" minProcessors="5" maxProcessors="75"
               enableLookups="true" redirectPort="2223"
               acceptCount="10" debug="0" connectionTimeout="60000"/>
    <Engine name="Standalone" defaultHost="localhost" debug="0">
      <Logger className="org.apache.catalina.logger.FileLogger"
              prefix="catalina_log." suffix=".txt" timestamp="true"/>
      <Realm className="org.apache.catalina.realm.MemoryRealm" />
      <Host name="localhost" debug="0" appBase="webapps" unpackWARs="true">
        <!-- Tomcat Root Context -->
        <Context path="" docBase="ROOT" debug="0"/>
    :
    :
        <!-- SimplePublisher examples -->
        <Context path="openjms" docBase="openjms" debug="0"
                 reloadable="true">
          <Logger className="org.apache.catalina.logger.FileLogger"
                     prefix="localhost_examples_log." suffix=".txt"
           timestamp="true"/>
        </Context>
      </Host>
    </Engine>
  </Service>
</Server>

Restarting Tomcat

Restart Tomcat, using either catalina or tomcat scripts files located in the bin directory. If the server comes up without any problems, the following will be displayed on the console:

Starting service Tomcat-Standalone
Apache Tomcat/4.0-b8-dev

Starting the OpenJMS Server

For simplicity, use the out-of-the-box RMI/JDBM configuration, rmi_jms.xml, for the server. Change to the bin directory of the OpenJMS installation and enter the following command line: startjms.bat -config ..\config\rmi_jms.xml

If the server has successfully started, the following output should appear in the console:

OpenJMS 0.7 (build 6)
Exolab Inc. (C) 1999-2001. All rights reserved. www.openjms.org
16:57:59.564 INFO [main] - Instantiated the RmiRegistryService service on port 1099
16:57:59.564 INFO [main] - Embedded RMI Registry running on port 1099
16:57:59.574 INFO [main] - Creating the RMI-based JMS Server
16:57:59.574 INFO [main] - Creating JNDI Server org.exolab.jms.jndi.rmi.RmiJndiServer
16:58:02.048 INFO [main] - Registered the service JndiServer with the registry.
16:58:02.048 INFO [main] - Started service [RmiRegistryService]
16:58:02.048 INFO [main] - Started service [ThreadPoolManager]
16:58:02.048 INFO [RmiRegistryService] - Started RmiRegistryService
16:58:12.052 INFO [main] - Started service [EventManagerThread]
16:58:12.252 INFO [main] - Removed expired messages.
16:58:12.252 INFO [main] - Started service [DatabaseService]
16:58:12.262 INFO [main] - Started service [Scheduler]
16:58:12.262 INFO [main] - Started service [LeaseManagerReaper]
16:58:12.262 INFO [main] - Started service [TransactionService]
16:58:12.262 INFO [main] - Started service [GCCollectionService]
16:58:12.392 INFO [main] - Started service [MessageManager]
16:58:12.402 INFO [main] - JMS Server is bound to //localhost:1099/OpenJmsServer
16:58:12.433 INFO [main] - JMS Admin Server is bound to //localhost:1099/JmsAdminServer
16:58:14.285 INFO [main] - Bound connection factory JmsQueueConnectionFactory
16:58:14.295 INFO [main] - Bound connection factory JmsTopicConnectionFactory

The important thing to note is that the server uses RMI with an embedded JNDI provider, called JndiServer, running on the localhost at port 1099. This information will be required by the user to formulate the URL.

Using the OpenJMS Web Application

Once the application has been deployed and both Tomcat and OpenJMS have been started, use the following URL to interact with the application: http://localhost:2222/openjms/servlets/SimplePublisher.html

The following page, excluding the information, will be rendered in the browser.

Dialogue box.
Figure 4.

Fill in the details, as specified above, and press Submit Query. This request will publish 20 messages under the topic jima.

Resources

OpenJMS

Jakarta Tomcat

Jim Alateras is an independent consultant specializing in open source and emerging technologies.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.