Caucho Technology
documentation
examples
changes

overview
quick start
installation
command-line
configuration
admin
amber
clustering
caching
database
deployment
ejb 3.0
embedding
filters
hessian
hmtp
ioc
jsp
logging
messaging
performance
quercus/php
remoting
scheduled tasks
security
server push
servlets
third-party
troubleshooting
virtual hosting
watchdog
webapp
xml and xslt

resin messaging


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.

Messaging hello, world

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.

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

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.

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

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-INF/resin-web.xml
<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>

JMS Queues

resin-web.xml - queue configuration
<web-app xmlns="http://caucho.com/ns/resin">

  <jms-queue name="my-queue" uri="memory:"/>
  <jms-connection-factory uri="resin:"/>

</web-app>

Memory Queue

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.

resin-web.xml - Memory queue and 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>

</web-app>

File Queue

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.

resin-web.xml - file queue and listener
<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>

Cluster Server Queue

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.

resin-web.xml - cluster server queue and listener
<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>

Cluster Client Queue

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.

resin-web.xml - client queue
<web-app xmlns="http://caucho.com/ns/resin">

  <jms-queue name="myQueue" uri="client:cluster=message-tier"/>

  <jms-connection-factory uri="resin:"/>

</web-app>

JMS Topics

resin-web.xml - topic configuration
<web-app xmlns="http://caucho.com/ns/resin">

  <jms-topic name="my-topic" uri="memory:"/>
  <jms-connection-factory uri="resin:"/>

</web-app>

Memory Topic

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.

resin-web.xml - Memory topic and listener
<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>

File Topic

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.

resin-web.xml - file topic and listener
<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>

ConnectionFactory

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

resin-web.xml - ConnectionFactory resource
<web-app xmlns="http://caucho.com/ns/resin">

  <jms-connection-factory name="jms/factory" uri="resin:"/>

</web-app>

BlockingQueue API

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.

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

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.

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

  <jms-queue uri="memory:"/>

</web-app>

BlockingQueue for 3rd party JMS

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.

Example: BlockingQueue WEB-INF/resin-web.xml
<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>

Message Driven Beans

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.

javax.jms.MessageListener
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.

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

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-INF/resin-web.xml
<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.

JCA - Java Connector Architecture (.rar files)

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.

JCA for message driven beans

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

WEB-INF/resin-web.xml ActiveMQ
<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-INF/resin-web.xml ActiveMQ
<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>

Third-party JMS providers


Copyright © 1998-2008 Caucho Technology, Inc. All rights reserved.
Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.