<document>
<localtoc/>

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

Because messaging is integrated with the Resin IoC container, applications can use standard WebBeans injection to obtain the queues, avoiding code dependencies and improving testing.

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

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

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); } }

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

package demo; import javax.jms.*; public MyListener implements MessageListener { public void onMessage(Message message) { ObjectMessage oMsg = (ObjectMessage) message; System.out.println("Received: " + oMsg.getObject()); } }

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-connection-factory uri="resin:"/> <jms-queue name="myQueue" uri="memory:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myQueue}</destination> </ejb-message-bean> <servlet-mapping url-pattern="/test" servlet-class="demo.MySendingServlet"/> </web-app> <web-app xmlns="http://caucho.com/ns/resin"> <jms-queue name="my-queue" uri="memory:"/> <jms-connection-factory uri="resin:"/> </web-app>

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 `BlockingQueue` API to send messages, and use a simple listener to receive messages.

<web-app xmlns="http://caucho.com/ns/resin"> <jms-connection-factory uri="resin:"/> <jms-queue name="myQueue" uri="memory:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myQueue}</destination> </ejb-message-bean> </web-app>

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.

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-queue name="myQueue" uri="file:path=WEB-INF/messaging"/> <jms-connection-factory uri="resin:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myQueue}</destination> </ejb-message-bean> </web-app>

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.

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-queue name="myQueue" uri="server:"> <init> <name>my-queue</name> <path>WEB-INF/jms</path> </init> </jms-queue> <jms-connection-factory uri="resin:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myQueue}</destination> </ejb-message-bean> </web-app>

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.

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-queue name="myQueue" uri="client:cluster=message-tier"/> <jms-connection-factory uri="resin:"/> </web-app> <web-app xmlns="http://caucho.com/ns/resin"> <jms-topic name="my-topic" uri="memory:"/> <jms-connection-factory uri="resin:"/> </web-app>

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 `BlockingQueue` API to send messages, and use a simple listener to receive messages.

<web-app xmlns="http://caucho.com/ns/resin"> <jms-connection-factory uri="resin:"/> <jms-topic name="myTopic" uri="memory:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myTopic}</destination> </ejb-message-bean> </web-app>

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.

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-topic name="myTopic" uri="file:path=WEB-INF/messaging"/> <jms-connection-factory uri="resin:"/> <ejb-message-bean class="demo.MyListener"> <destination>#{myTopic}</destination> </ejb-message-bean> </web-app>

The `ConnectionFactory` resource defines the JMS factory for creating JMS connections.

<web-app xmlns="http://caucho.com/ns/resin"> <jms-connection-factory name="jms/factory" uri="resin:"/> </web-app>

Resin's queues implement the `java.util.concurrent.BlockingQueue` API. Since the queues are registered with Resin-IoC it's possible to use the `BlockingQueue` API directly without the JMS API.

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()); } }

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-queue uri="memory:"/> </web-app>

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

<web-app xmlns="http://caucho.com/ns/resin"> <resource-adapter class="org.apache.activemq.ra.ActiveMQResourceAdapter"> <init server-url="vm://localhost"/> </resource-adapter> <connection-factory uri="activemq:" name="factory"/> <jms-queue uri="activemq:" name="queue"> <init physicalName="queue.test"/> </jms-queue> <bean name="test" class="com.caucho.jms.queue.JmsBlockingQueue"> <init> <factory>${factory}</factory> <destination>${queue}</destination> </init> </bean> </web-app>

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.

package javax.jms; public interface MessageListener { public void onMessage(Message message); }

The implementation class can use any Resin IoC capability, including injection, transaction annotations or interception. For example, a simple listener might use Amber/JPA to store messages in a database.

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(); } } }

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

<web-app xmlns="http://caucho.com/ns/resin"> <jms-connection-factory uri="resin:"/> <jms-queue name="my_queue" uri="memory:"/> <ejb-message-bean class="demo.MyListener"> <destination>${my_queue}</destination> </ejb-message-bean> </web-app>

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

Because the `<ejb-message-bean>` is a Resin IoC bean, it can use an optional `<init>` block to configure any parameters of `MyListener`.

The Java Connector Architecture is a driver architecture which connects JMS providers like ActiveMQ with Resin's message driven beans and JMS sessions. The JCA driver will configure a resource adapter and an activation spec to select a queue.

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

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

<web-app xmlns="http://caucho.com/ns/resin"> <resource-adapter class="org.apache.activemq.ra.ActiveMQResourceAdapter"> <init server-url="vm://localhost"/> </resource> <ejb-message-bean class="qa.MyListener"> <activation-spec class="org.apache.activemq.ra.ActiveMQActivationSpec"> <init physical-name="queue.test"/> </activation-spec> </ejb-message-bean> </web-app>

Resin can also provide shortcuts for the driver classes using the uri syntax:

<web-app xmlns="http://caucho.com/ns/resin"> <resource-adapter uri="activemq:"> <init server-url="vm://localhost"/> </resource> <ejb-message-bean class="qa.MyListener"> <activation-spec uri="activemq:"> <init physical-name="queue.test"/> </activation-spec> </ejb-message-bean> </web-app>

- ActiveMQ and Resin

</document>