<?xml version="1.0" ?>
<!--DOCTYPE document [
  <!ENTITY project SYSTEM "project.xml">
]-->
<?xml-stylesheet type="text/xsl" href="tomcat.xsl"?>

<document url="jndi-jms-examples-howto.html">

    <!--&project;-->

    <properties>
        <author email="fabien(dot)carrion(at)gmail(dot)com">Fabien Carrion</author>
        <title>JNDI JMS HOW-TO</title>
    </properties>

<body>

<section name="Table of Contents">
<p>
<a href="#Introduction">Introduction</a><br />
<a href="#JMS Configurations">JMS Configurations</a><br />
</p>
</section>

<section name="Introduction">

<p>JNDI JMS configuration is covered extensively in the
JNDI-Resources-HOWTO.  However, feedback from <code>tomcat-user</code>
has shown that specifics for individual configurations can be rather
tricky.</p>

<p>Here then are some example configurations that have been posted to
tomcat-user for popular MOM and some general tips for messages
useage.</p>

<p>You should be aware that since these notes are derived from
configuration and/or feedback posted to <code>tomcat-user</code> YMMV
:-). Please let us know if you have any other tested configurations
that you feel may be of use to the wider audience, or if you feel we
can improve this section in anyway.</p>

<p><b>Please note that this document has been written for tomcat 6.0.x.</b>
</p>

<p>Also, please note that JNDI JMS configuration in general, and this
tutorial in particular, assumes that you have read and understood the
<a href="config/context.html">Context</a> and <a
href="config/host.html">Host</a> configuration references, including
the section about Automatic Application Deployment in the latter
reference.
</p>
</section>

<section name="JMS Configurations">

<subsection name="ActiveMQ Broker Example">

<h3>0. Introduction</h3>
<p>Versions of <a href="http://www.activemq.org">ActiveMQ</a> that has been reported to work:
<ul>
<li>ActiveMQ 4.1.0-incubator</li>
</ul>
</p>

<p>Before you proceed, don't forget to copy the JMS Driver's jar into
<code>$CATALINA_HOME/lib</code>. In that case it is
apache-activemq-4.1.0-incubator.jar.</p>

<h3>1. ActiveMQ configuration</h3>

<p>ActiveMQ doesn't need any particular configuration. It's possible to
get it work from a binary distribution.</p>

<h3>2. server.xml configuration</h3>

<p>Configure the JNDI DataSource in Tomcat by adding a declaration for
your resource to <code>$CATALINA_HOME/conf/server.xml</code>.</p>

<p>Add this in between the <code>&lt;/Context&gt;</code> tag of the
examples context and the <code>&lt;/Host&gt;</code> tag closing the
localhost definition.  If there is no such tag, you can add one as
illustrated in the <a href="config/context.html">Context</a> and <a
href="config/host.html">Host</a> configuration references, and
repeated below for your convenience.
</p>

<p>You can find more connection parameters and their descriptions on this
<a href="http://maven.reucon.com/public/org/apache/activemq/activemq-core/4.1.0-incubator/activemq-core-4.1.0-incubator.xsd.html">
page</a>.

<source>
&lt;Context path="/JMSTest" docBase="JMSTest"
        debug="5" reloadable="true" crossContext="true"&gt;

    &lt;!-- factory: The class who's going to create the objects we need.
         --&gt;

    &lt;!-- brokerURL: The broker URL to set.
         --&gt;

    &lt;!-- brokerName: The name of the broker to use if
            creating an embedded broker.
         --&gt;

    &lt;!-- userName and password: ActiveMQ username and password
            for JMS connections.
         --&gt;

    &lt;!-- useEmbeddedBroker: Allows embedded brokers to be
            associated with a connection factory.
         --&gt;

    &lt;!-- clientID: String identification to use when connection to a
            topic.
         --&gt;

    &lt;!-- physicalName: The name for the JMS destination.
         --&gt;

    &lt;Resource name="jms/ConnectionFactory" auth="Container"
                 type="org.apache.activemq.ActiveMQConnectionFactory"
                 description="JMS Connection Factory"
                 factory="org.apache.activemq.jndi.JNDIReferenceFactory"
                 brokerURL="vm://localhost"
                 brokerName="LocalActiveMQBroker"
                 userName="activemq" password="activemq"
                 useEmbeddedBroker="false"
                 clientID="TomcatClientID" /&gt;

    &lt;Resource name="jms/myQueue" auth="Container"
                 type="org.apache.activemq.command.ActiveMQQueue"
                 description="JMS Queue"
                 factory="org.apache.activemq.jndi.JNDIReferenceFactory"
                 physicalName="TEST.FOO" /&gt;

    &lt;Resource name="jms/myTopic" auth="Container"
                 type="org.apache.activemq.command.ActiveMQTopic"
                 description="JMS Topic"
                 factory="org.apache.activemq.jndi.JNDIReferenceFactory"
                 physicalName="TEST.BAR"/&gt;

&lt;/Context&gt;

</source>
</p>

<h3>3. web.xml configuration</h3>

<p>Now create a <code>WEB-INF/web.xml</code> for this test application.
<source>
&lt;web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
            http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4"&gt;
  &lt;description&gt;ActiveMQ Test App&lt;/description&gt;
  &lt;servlet&gt;
      &lt;servlet-name&gt;Test&lt;/servlet-name&gt;
      &lt;servlet-class&gt;test&lt;/servlet-class&gt;
  &lt;/servlet&gt;
  &lt;servlet-mapping&gt;
      &lt;servlet-name&gt;Test&lt;/servlet-name&gt;
      &lt;url-pattern&gt;/test.do&lt;/url-pattern&gt;
  &lt;/servlet-mapping&gt;
  &lt;message-destination-ref&gt;
      &lt;message-destination-ref-name&gt;jms/myQueue&lt;/message-destination-ref-name&gt;
      &lt;message-destination-type&gt;javax.jms.Queue&lt;/message-destination-type&gt;
      &lt;message-destination-usage&gt;ConsumesProduces&lt;/message-destination-usage&gt;
      &lt;message-destination-link&gt;MyQueue&lt;/message-destination-link&gt;
  &lt;/message-destination-ref&gt;
  &lt;message-destination&gt;
      &lt;message-destination-name&gt;MyQueue&lt;/message-destination-name&gt;
  &lt;/message-destination&gt;
&lt;/web-app&gt;
</source>
</p>

<h3>4. Test code</h3>

<p>Now create a simple <code>WEB-INF/classes/test.java</code> class for use later.
<source>
import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import javax.jms.*;
import javax.naming.InitialContext;

public class test extends HttpServlet {


    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
        throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String body = "";

          try {
              InitialContext init = new InitialContext();

              javax.jms.Queue destination =
                  (javax.jms.Queue) init.lookup("java:comp/env/jms/myQueue");
              ConnectionFactory connectionFactory =
                  (ConnectionFactory) init.lookup("java:comp/env/jms/ConnectionFactory");
              Connection connection = connectionFactory.createConnection();
              Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

              TextMessage message = session.createTextMessage();
              message.setText("My text message was send and received");
              connection.start();

              MessageProducer producer = session.createProducer(destination);
              producer.setDeliveryMode(DeliveryMode.PERSISTENT);
              producer.send(message);
              message = null;

              MessageConsumer consumer = session.createConsumer(destination);
              message = (TextMessage) consumer.receive(1000);
              if( message!=null ) {
                  body = message.getText();
              }

              producer.close();
              consumer.close();
              session.close();
              connection.close();

          } catch (Exception e) {
              System.out.println(e.toString());
          }

        out.println("&lt;html&gt;");
        out.println("&lt;head&gt;");

	    String title = "JMS Test";

	    out.println("&lt;title&gt;" + title + "&lt;/title&gt;");
        out.println("&lt;/head&gt;");
        out.println("&lt;body bgcolor=\"white\"&gt;");

        out.println("&lt;h1&gt;" + title + "&lt;/h1&gt;");

        out.println("&lt;p&gt;The message contains \"" + body + "\".&lt;/p&gt;");

        out.println("&lt;/body&gt;");
        out.println("&lt;/html&gt;");

    }
}
</source>
</p>


<p>Finally deploy your web app into
<code>$CATALINA_HOME/webapps</code> either as a warfile called
<code>JMSTest.war</code> or into a sub-directory called
<code>JMSTest</code></p>

<p>Once deployed, point a browser at
<code>http://localhost:8080/JMSTest/test.do</code> to view the fruits
of your hard work.</p>

</subsection>

<subsection name="Joram Broker Example">

<h3>0. Introduction</h3>
<p>Versions of <a href="http://joram.objectweb.org/">Joram</a> that has been reported to work:
<ul>
<li>Joram 4.3.21</li>
</ul>
</p>

<p>Before you proceed, don't forget to copy the JMS Driver's jar into
<code>$CATALINA_HOME/lib</code>. In that case it is
joram-client.jar, joram-connector.jar, joram-shared.jar,
ow_monolog.jar, JCup.jar and jms.jar.</p>

<h3>1. Joram configuration</h3>

<p>First you have to set the JORAM_HOME environment variable. Then to start up the
server, execute the script $JORAM_HOME/samples/bin/single_server.sh. To configure the
server, execute $JORAM_HOME/samples/bin/admin.sh. In the menu Admin, choose connect.
Fill the username with root and the password with root and validate with the button connect.
Then in the menu JNDI, choose connect and validate with the button connect. Then you
have to create connection factory, queue and topic. You will need the Destination identifier
for each queue and topic, you're going to use. You need also to create a user with name
"anonymous" and password "anonymous".</p>

<h3>2. server.xml configuration</h3>

<p>In a similar manner to the activemq config above, you will need to
define your Resource in your server.xml file. Here we define a
Resource called jms/ConnectionFactory.</p>

<p>
<source>
    &lt;!-- factory: The class who's going to create the objects we need.
         --&gt;

    &lt;!-- cFactory.host: Name or IP address of the server's host.
         --&gt;

    &lt;!-- cFactory.port: Server's listening port.
         --&gt;

    &lt;!-- cFactory.url: url to connect to joram
         --&gt;

    &lt;!-- cFactory.cnxT: Duration in seconds during which connecting is
            attempted (connecting might take time if the server is temporarily
            not reachable); the 0 value is set for connecting only once and
            aborting if connecting failed.
         --&gt;

    &lt;!-- cFactory.txT: Duration in seconds during which a JMS transacted 
            (non XA) session might be pending; above that duration the session
            is rolled back and closed; the 0 value means "no timer".
         --&gt;

    &lt;!-- cFactory.cnxPT: Period in milliseconds between two ping requests sent
            by the client connection to the server; if the server does not receive
            any ping request during more than 2 * cnxPendingTimer, the connection
            is considered as dead and processed as required.
         --&gt;

    &lt;!-- cFactory.asyncSend: Determines whether the produced messages are
            asynchronously sent or not (without or with acknowledgement)
            Default is false (with ack).
         --&gt;

    &lt;!-- cFactory.queueMessageReadMax: The maximum number of messages that can
            be read at once from a queue. Default is 1.
         --&gt;

    &lt;!-- reliableClass: Reliable class name, for exemple use by ssl.
         --&gt;

    &lt;!-- dest.name: It is the destination Identifier which you can get in the
            JORAM Administration Tool. I don't know why you have to use the destination
            Identifier and not the JNDI name. It's a question to ask to the JORAM
            development team. My personal opinion is that in the class ObjectFactory
	    when they want to create a Queue, they use the name of the queue as agentid,
	    while they should do a naming lookup to know the agentid with LookupRequest
	    and LookupReply.
         --&gt;

    &lt;Resource name="jms/ConnectionFactory" auth="Container"
                 type="org.objectweb.joram.client.jms.tcp.TcpConnectionFactory"
                 description="JMS Connection Factory"
                 factory="org.objectweb.joram.client.jms.admin.ObjectFactory"
                 cFactory.host="localhost" cFactory.port="16010"
                 cFactory.cnxT="1000" cFactory.txT="1000" cFactory.cnxPT="1000"
                 cFactory.asyncSend="false" cFactory.queueMessageReadMax="1"
                 reliableClass="" /&gt;

    &lt;Resource name="jms/myQueue" auth="Container"
                 type="org.objectweb.joram.client.jms.Queue"
                 description="JMS Queue"
                 factory="org.objectweb.joram.client.jms.admin.ObjectFactory"
                 dest.name="#0.0.1026" /&gt;

    &lt;Resource name="jms/myTopic" auth="Container"
                 type="org.objectweb.joram.client.jms.Topic"
                 description="JMS Topic"
                 factory="org.objectweb.joram.client.jms.admin.ObjectFactory"
                 dest.name="#0.0.1027" /&gt;
</source>
</p>

<h3>3. web.xml configuration</h3>

<p>The tags to insert in the web.xml are the same like to insert in the
ActiveMQ web.xml.</p>

<h3>4. Test code</h3>

<p>The code to test the Joram server is the same like to test the ActiveMQ one.</p>

</subsection>


<subsection name="OpenJms Broker Example">

<h3>0. Introduction</h3>
<p>Versions of <a href="http://openjms.sourceforge.net/">OpenJms</a> that has been reported to work:
<ul>
<li>OpenJms 0.7.7 alpha 3</li>
</ul>
</p>

<p>Before you proceed, don't forget to copy the JMS Driver's jar into
<code>$CATALINA_HOME/lib</code>. In that case it is
concurrent-1.3.4.jar, openjms-0.7.7-alpha-3.jar,
openjms-common-0.7.7-alpha-3.jar, openjms-net-0.7.7-alpha-3.jar,
commons-codec-1.3.jar, jms-1.1.jar, jndi-1.2.1.jar and
spice-jndikit-20050704.053804.jar.</p>

<h3>1. OpenJms configuration</h3>

<p>OpenJms doesn't need any particular configuration. It's possible to
get it work from a binary distribution.</p>

<h3>2. server.xml configuration</h3>

<p>In a similar manner to the activemq config above, you will need to
define your Resource in your server.xml file. Here we define a
Resource called jms/ConnectionFactory.</p>

<p>
<source>
   &lt;!-- type: org.exolab.jms.client.JmsConnectionFactory or
                 org.exolab.jms.client.JmsXAConnectionFactory
         --&gt;

    &lt;!-- factory: The class who's going to create the objects we need.
         --&gt;

    &lt;!-- serverClass: The class to use to make the connection
         --&gt;

    &lt;!-- org.exolab.jms.net.orb.provider.uri: The broker URL to set.
         --&gt;

    &lt;!-- org.exolab.jms.net.orb.security.principal: OpenJms username for
            JMS connections.
         --&gt;

    &lt;!-- org.exolab.jms.net.orb.security.credentials: OpenJms password
            for JMS connections.
         --&gt;

    &lt;!-- name: The JNDI name for the JMS destination on the OpenJms server and
            The JNDI name in the Tomcat context. Both servers use the same parameter
            and Tomcat don't forward the name parameter to the OpenJms client library.
            So it isn't possible to declare a JMS destination resource. You have to use
            the createDestination method.
         --&gt;

    &lt;!-- persistent: Is the destination persitent ?
         --&gt;

    &lt;Resource name="jms/ConnectionFactory" auth="Container"
                 type="org.exolab.jms.client.JmsConnectionFactory"
                 description="JMS Connection Factory"
                 factory="org.exolab.jms.client.JmsConnectionFactoryBuilder"
                 serverClass="org.exolab.jms.client.net.JmsServerStubImpl"
                 org.exolab.jms.net.orb.provider.uri="tcp://localhost:3035/"
                 org.exolab.jms.net.orb.security.principal=""
                 org.exolab.jms.net.orb.security.credentials="" /&gt;

    &lt;!--Resource name="jms/myQueue" auth="Container"
                 type="org.exolab.jms.client.JmsQueue"
                 description="my Queue"
                 factory="org.exolab.jms.client.JmsDestinationFactory"
                 name="queue1" persistent="true" /--&gt;

    &lt;!--Resource name="jms/myTopic" auth="Container"
                 type="org.exolab.jms.client.JmsTopic"
                 description="my Topic"
                 factory="org.exolab.jms.client.JmsDestinationFactory"
                 name="topic1" persistent="true" /--&gt;

</source>
</p>

<h3>3. web.xml configuration</h3>

<p>We don't have to insert any tag in the web.xml, because we can't declare JMS
destinations resource in the server.xml.</p>

<h3>4. Test code</h3>

<p>We can't declare this resource in the server.xml file. So we can't use it in a
servlet from the tomcat context</p>

</subsection>

<subsection name="Jboss Messaging Broker Example">

<h3>0. Introduction</h3>
<p>Versions of <a href="http://www.jboss.com/products/messaging">Jboss Messaging</a>
that has been reported to work:
<ul>
<li>Jboss Messaging 1.2.0 Beta2</li>
</ul>
</p>

<p>Before you proceed, don't forget to copy the JMS Driver's jar into
<code>$CATALINA_HOME/lib</code>. In that case it is
jboss-messaging-client.jar.</p>

<h3>1. Jboss Messaging configuration</h3>

<p>Jboss Messaging doesn't need any particular configuration. It's possible to
get it work from a binary distribution.</p>

<p>Jboss Messaging implements the interface javax.naming.spi.ObjectFactory.
The classes are org.jboss.jms.referenceable.ConnectionFactoryObjectFactory and
org.jboss.jms.referenceable.DestinationObjectFactory. But the parameter JBM-CF for the
connection factory and the parameter JBM-DEST for the destination factory have to be set
with an object, which is not possible in a configuration file.</p>

</subsection>

</section>

</body>
</document>

