<document>
  <header>
    <product>resin</product>
    <title>Resin Messaging</title>
    <description>
      <p>Configuration for Resin's JMS provider implementation.  The JDBC Queues and Topics provide a persistent messaging store.  The Memory Queues and Topics provide a low-overhead memory-based store.</p>
    </description>
  </header>

  <body>
    <localtoc/>

<s1 title="Messaging hello, world">

<p>Resin's messaging is build around JMS, the Java
messaging service API and EJB message driven beans.  A simple messaging
application can use the <code>BlockingQueue</code> API to send messages
and implement a <code>MessageListener</code> to receive messages.</p>

<p>Because messaging is integrated with the <a href="resin-ioc.xtp">Resin IoC
container</a>, applications can use standard WebBeans injection to
obtain the queues, avoiding code dependencies and improving testing.</p>

<p>The following example sends a "hello, world" message
from <code>MySendingServlet</code> and processes it
in <code>MyListener</code>.  The servlet does not wait for the listener,
it completes immediately.  The <code>MyListener</code> message bean
will receive the message when it's available.</p>

<p>The <code>@Named</code> WebBeans annotation tells Resin to look
for a configured <code>BlockingQueue</code> named "myQueue" and inject
it into the <code>_queue</code> variable when the servlet is initialized.
The <code>offer</code> method sends the message to the JMS queue using
a JMS <code>ObjectMessage</code>.
</p>

<example title="demo/MySendingServlet.java">
package demo;

import java.io.*;
import javax.servlet.*;
import java.util.BlockingQueue;
import javax.webbeans.Named;

public MySendingServlet extends GenericServlet
{
  @Named("myQueue") private BlockingQueue _queue;

  public void service(ServletRequest req, ServletResponse res)
    throws IOException, ServletException
  {
    String msg = "hello, world";

    _queue.offer(msg);

    System.out.println("Sent: " + msg);
  }
}
</example>

<p>The EJB message bean service will receive the message and pass it
along to <code>MyListener</code>.  Since Resin's <code>BlockingQueue</code>
API automatically wraps the object in a JMS <code>ObjectMessage</code>,
<code>MyListener</code> needs to unwrap it.</p>

<example title="demo/MyListener.java">
package demo;

import javax.jms.*;

public MyListener implements MessageListener
{
  public void onMessage(Message message)
  {
    ObjectMessage oMsg = (ObjectMessage) message;

    System.out.println("Received: " + oMsg.getObject());
  }
}
</example>

<p>Now that the code's written, we just need to configure it in the
<code>WEB-INF/resin-web.xml</code>.  The &lt;jms-connection-factory>
configures Resin as the JMS provider, the &lt;jms-queue> configures
a memory-based queue as the implementation, and the &lt;ejb-message-bean>
configures our listener.</p>

<example title="WEB-INF/resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-connection-factory uri="resin:"/>
  &lt;jms-queue name="myQueue" uri="memory:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myQueue}&lt;/destination>
  &lt;/ejb-message-bean>

  &lt;servlet-mapping url-pattern="/test"
                   servlet-class="demo.MySendingServlet"/>

&lt;/web-app>
</example>

</s1>

<s1 title="JMS Queues">

<example title="resin-web.xml - queue configuration">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-queue name="my-queue" uri="memory:"/>
  &lt;jms-connection-factory uri="resin:"/>

&lt;/web-app>
</example>

<s2 title="Memory Queue">

<p>Resin's memory queue is a basic, non-persistent queue suitable
for testing and for cases where losing the queue contents at a server
crash is acceptable.  Like Resin's other queues, you can use the
<code>BlockingQueue</code> API to send messages, and use a simple
listener to receive messages.</p>

<example title="resin-web.xml - Memory queue and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-connection-factory uri="resin:"/>
  &lt;jms-queue name="myQueue" uri="memory:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myQueue}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

<s2 title="File Queue">

<p>The file queue backs messages on the local filesystem, allowing
for recovery in case of system crash.  The saved file is efficient,
using the same backing store as Resin's proxy caching and
persistent sessions.</p>

<p>The file queue configuration requires an additional 'path' parameter
to specify a directory for the backing files.</p>

<example title="resin-web.xml - file queue and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-queue name="myQueue" uri="file:path=WEB-INF/messaging"/>

  &lt;jms-connection-factory uri="resin:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myQueue}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

<s2 title="Cluster Server Queue">

<p>The cluster server queue is a file queue which can also receive
messages from the local cluster.  On the local machine, it acts exactly
like the file queue.  When used with the cluster client queue, clients
can distribute messages to any server queue in the cluster, allowing
for load balancing.</p>

<p>Like the file queue, the cluster server queue requires a 'path' attribute
to specify the location of the backing file.</p>

<example title="resin-web.xml - cluster server queue and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-queue name="myQueue" uri="server:">
    &lt;init>
      &lt;name>my-queue&lt;/name>
      &lt;path>WEB-INF/jms&lt;/path>
    &lt;/init>
  &lt;/jms-queue>

  &lt;jms-connection-factory uri="resin:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myQueue}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

<s2 title="Cluster Client Queue">

<p>The client queue distributes messages to server queues in a
cluster.  Normally, only the sending methods are used for the client
queue; the receiving message beans are handled by the server queues.</p>

<p>The client queue needs to configure the cluster of the server queues.
The cluster can be different from the client's own cluster.</p>

<example title="resin-web.xml - client queue">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-queue name="myQueue" uri="client:cluster=message-tier"/>

  &lt;jms-connection-factory uri="resin:"/>

&lt;/web-app>
</example>

</s2>

</s1>

<s1 title="JMS Topics">

<example title="resin-web.xml - topic configuration">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-topic name="my-topic" uri="memory:"/>
  &lt;jms-connection-factory uri="resin:"/>

&lt;/web-app>
</example>

<s2 title="Memory Topic">

<p>Resin's memory topic is a basic, non-persistent topic suitable
for testing and for cases where losing the topic contents at a server
crash is acceptable.  Like Resin's other topics, you can use the
<code>BlockingQueue</code> API to send messages, and use a simple
listener to receive messages.</p>

<example title="resin-web.xml - Memory topic and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-connection-factory uri="resin:"/>
  &lt;jms-topic name="myTopic" uri="memory:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myTopic}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

<s2 title="File Topic">

<p>The file topic backs messages on the local filesystem for
persistent subscriptions.  Non-persistent subscriptions use
the memory topic interface.  The saved file is efficient,
using the same backing store as Resin's proxy caching and
persistent sessions.</p>

<p>The file topic configuration requires an additional 'path' parameter
to specify a directory for the backing files.</p>

<example title="resin-web.xml - file topic and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-topic name="myTopic" uri="file:path=WEB-INF/messaging"/>

  &lt;jms-connection-factory uri="resin:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myTopic}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>
<!--
<s2 title="Cluster Server Topic">

<p>The cluster server topic is a file topic that serves as a hub for
messages from the local cluster.  On the local machine, it acts exactly
like the file topic.  When used with the cluster client topic, clients
can distribute messages to any server topic in the cluster, allowing
for load balancing.</p>

<p>Like the file topic, the cluster server topic requires a 'path' attribute
to specify the location of the backing file.</p>

<example title="resin-web.xml - cluster server topic and listener">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-topic name="myTopic" uri="server:">
    &lt;init>
      &lt;name>my-topic&lt;/name>
      &lt;path>WEB-INF/jms&lt;/path>
    &lt;/init>
  &lt;/jms-topic>

  &lt;jms-connection-factory uri="resin:"/>

  &lt;ejb-message-bean class="demo.MyListener">
    &lt;destination>#{myTopic}&lt;/destination>
  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

<s2 title="Cluster Client Topic">

<p>The client topic distributes messages to server topics in a
cluster.  Normally, only the sending methods are used for the client
topic; the receiving message beans are handled by the server topics.</p>

<p>The client topic needs to configure the cluster of the server topics.
The cluster can be different from the client's own cluster.</p>

<example title="resin-web.xml - client topic">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-topic name="myTopic" uri="client:cluster=message-tier"/>

  &lt;jms-connection-factory uri="resin:"/>

&lt;/web-app>
</example>

</s2>
-->
</s1>

<s1 title="ConnectionFactory">

<p>The <code>ConnectionFactory</code> resource defines the JMS factory
for creating JMS connections.</p>

<example title="resin-web.xml - ConnectionFactory resource">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-connection-factory name="jms/factory" uri="resin:"/>

&lt;/web-app>
</example>

<!-- XXX: ??
<p>
If an application creates a named queue or topic using the the JMS Session,
Resin's default behaviour is to create a memory queue or topic.  The 
<a href="#jdbc-manager">jdbc-manager</a> configuration of the connection factory 
causes creation of a jdbc queue or topic instead.
</p>

<example title="ConnectionFactory resource">
&lt;resource jndi-name="jms/factory"
           type="com.caucho.jms.ConnectionFactoryImpl"/&gt;
  &lt;init&gt;
    &lt;jdbc-manager&gt;
      &lt;data-source&gt;jdbc/database&lt;/data-source&gt;
    &lt;/jdbc-manager&gt;
  &lt;/init&gt;
&lt;/resource&gt;
</example>

<deftable-childtags>
<tr><td>client-id</td>
    <td>clientID value for durable subscriptions</td>
    <td>pseudo-random generated value</td>
    </tr>
<tr><td>jdbc-manager</td>
    <td>Use jdbc queues and topics for queues and topics created using the JMS Session object,
        see <a href="#jdbc-manager">jdbc-manager</a></td>
    <td>use a memory queue for created queues and topics</td>
    </tr>
</deftable-childtags>
-->
</s1>

<s1 title="BlockingQueue API">

<p>Resin's queues implement
the <code>java.util.concurrent.BlockingQueue</code> API.
Since the queues are registered with <a href="resin-ioc.xtp">Resin-IoC</a>
it's possible to use the <code>BlockingQueue</code> API directly
without the JMS API.</p>

<example title="TestServlet for JMS/BlockingQueue">
package example;

import java.util.concurrent.BlockingQueue;
import java.io.*;
import javax.servlet.*;
import javax.webbeans.*;

public class TestServlet extends GenericServlet {
  private @In BlockingQueue _queue;

  public void service(ServletRequest req, ServletResponse res)
    throws IOException, ServletException
  {
    PrintWriter out = res.getWriter();

    _queue.offer("test message");

    out.println("receive: " + _queue.poll());
  }
}
</example>

<p>The resin-web.xml configuration for the <code>BlockingQueue</code>
API is simple, only requiring the &lt;jms-queue> tag.  Because the
<code>BlockingQueue</code> uses Resin's JMS queue implementation directly,
it already knows where to get the <code>ConnectionFactory</code>.</p>

<example title="resin-web.xml configuration for memory BlockingQueue">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-queue uri="memory:"/>

&lt;/web-app>
</example>

<s2 title="BlockingQueue for 3rd party JMS">

<p>The <code>BlockingQueue</code> API is also available for other JMS
providers.  You'll need to configure a <code>JmsBlockingQueue</code> in
the resin-web.xml to take advantage of it.</p>

<example title="Example: BlockingQueue WEB-INF/resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;resource-adapter class="org.apache.activemq.ra.ActiveMQResourceAdapter">
      &lt;init server-url="vm://localhost"/>
  &lt;/resource-adapter>

   &lt;connection-factory uri="activemq:" name="factory"/>
 
   &lt;jms-queue uri="activemq:" name="queue">
       &lt;init physicalName="queue.test"/>
   &lt;/jms-queue>
 
  &lt;bean name="test" class="com.caucho.jms.queue.JmsBlockingQueue">
    &lt;init>
      &lt;factory>${factory}&lt;/factory>
      &lt;destination>${queue}&lt;/destination>
    &lt;/init>
  &lt;/bean>

&lt;/web-app>
</example>

</s2>

</s1>

<s1 title="Message Driven Beans">

<p>At some point, the application needs to receive messages from the
and process them.   Message driven beans provides a reliable, pooled
framework for receiving messages.  Applications just need to implement
a simple listener interface, and register to listen with a queue or topic.
</p>

<def title="javax.jms.MessageListener">
package javax.jms;

public interface MessageListener {

  public void onMessage(Message message);

}
</def>

<p>The implementation class can use any <a href="resin-ioc.xtp">Resin IoC</a>
capability, including injection, transaction annotations or interception.
For example, a simple listener might use <a href="amber.xtp">Amber/JPA</a> to
store messages in a database.</p>

<example title="demo/MyListener.java">
package demo;

import javax.jms.*;
import javax.persistence.*;
import javax.webbeans.*;

public class MyListener implements MessageListener
{
  private @In EntityManagerFactory _factory;

  public void onMessage(Message msg)
  {
    ObjectMessage oMsg = (ObjectMessage) msg;

    String value = oMsg.getObject();

    EntityManager em = _factory.createEntityManager();

    try {
      em.persist(new MyEntry(value));
    } finally {
      em.close();
    }
  }
}
</example>

<p>The configuration in the resin-web.xml file will connect the
<code>MyListener</code> class with the queue.  In this case, we'll
use the simple memory queue.</p>

<example title="WEB-INF/resin-web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;jms-connection-factory uri="resin:"/>
  &lt;jms-queue name="my_queue" uri="memory:"/>

  &lt;ejb-message-bean class="demo.MyListener">

    &lt;destination>${my_queue}&lt;/destination>

  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

<p>The <code>&lt;ejb-message-bean></code> tag configures the message bean
pool with the application's listener specified by the <code>class</code>.
Resin will automatically create several <code>MyListener</code> instances
to process any queue messages.  The <code>&lt;destination></code> tag
specifies the queue to use.</p>

<p>Because the <code>&lt;ejb-message-bean></code> is a Resin IoC bean, it
can use an optional <code>&lt;init></code> block to configure any
parameters of <code>MyListener</code>.</p>

</s1>

<s1 title="JCA - Java Connector Architecture (.rar files)">

<p>The Java Connector Architecture is a driver architecture which
connects JMS providers like <a href="http://wiki.caucho.com/ActiveMQ">ActiveMQ</a>
with Resin's message driven beans and JMS sessions.  The JCA driver
will configure a <a href="http://wiki.caucho.com/Resource_Adapter">resource
adapter</a> and an <a href="http://wiki.caucho.com/Activation_Spec">activation
spec</a> to select a queue.</p>

<p>The resource adapter is the JCA driver's main service.  It handles
threading, socket connections, and creates any endpoints.</p>

<s2 title="JCA for message driven beans">

<p>The activation specification configures the JCA driver with a
message-driven bean.  The configuration looks like:</p>

<example title="WEB-INF/resin-web.xml ActiveMQ">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;resource-adapter class="org.apache.activemq.ra.ActiveMQResourceAdapter">
    &lt;init server-url="vm://localhost"/>
  &lt;/resource>

  &lt;ejb-message-bean class="qa.MyListener">

    &lt;activation-spec class="org.apache.activemq.ra.ActiveMQActivationSpec">
      &lt;init physical-name="queue.test"/>
    &lt;/activation-spec>

  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

<p>Resin can also provide shortcuts for the driver classes using the
uri syntax:</p>

<example title="WEB-INF/resin-web.xml ActiveMQ">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;resource-adapter uri="activemq:">
    &lt;init server-url="vm://localhost"/>
  &lt;/resource>

  &lt;ejb-message-bean class="qa.MyListener">

    &lt;activation-spec uri="activemq:">
      &lt;init physical-name="queue.test"/>
    &lt;/activation-spec>

  &lt;/ejb-message-bean>

&lt;/web-app>
</example>

</s2>

</s1>

<s1 title="Third-party JMS providers">

<ul>
<li><a href="http://wiki.caucho.com/ActiveMQ">ActiveMQ and Resin</a></li>
</ul>

</s1>

</body>
</document>
