Caucho Technology
  • resin 4.0
  • jms listener with ejb message bean


    Introduces receiving a message using an EJB message bean.

    Demo

    Files in this tutorial

    FILEDESCRIPTION
    WEB-INF/web.xmlConfigures the Queue, MessageSender, MessageListener.
    WEB-INF/classes/example/MyListener.javaThe message listener.
    WEB-INF/classes/example/MessageServlet.javaThe message servlet

    Overview

    Messaging decouples a sending task from a receiving/processing task, allowing for batch processing or load balancing of tasks to another machine. The original task can respond immediately to the user without waiting for the task complete. The servlet creates a message and sends it to a queue. The servlet immediately completes and when the batch process is ready, it processes the message.

    Messaging is therefore comprised of three main components:

    • A Producer creates messages and sends them to a Queue. The Producer could be something like a Servlet.
    • A Queue stores the messages from the Produces and provides them to a Consumer when ready. The Queue is implemented by the messaging provider.
    • A Consumer processes messages as they become available in the Queue. The Consumer is typically a bean implementing the MessageListener interface.

    Producer (MessageServlet)

    In this example, the Producer is a Servlet which sends a simple message. To simplify the example, we'll use the BlockingQueue API instead of the JMS producers. The functionality is the same without the extra housekeeping of the JMS API.

    The servlet uses CDI dependency injection to get the BlockingQueue. The dependency injection cleans the code by decoupling it from the implementation. For example, the actual BlockingQueue could be facade around another JMS implementation's queue.

    Example: MessageServlet
    import javax.inject.Inject;
    import java.util.concurrent.BlockingQueue;
    
    public class MessageServlet extends GenericServlet {
      @Inject BlockingQueue _sender;
    
      ...
      String message = "sample message";
      _sender.put(message);
    }
    

    In this configuration, the BlockingQueue is a java.util.concurrent.BlockingQueue. It's also possible to use the full JMS MessageProducer which is more verbose.

    The put method completes as soon as the message is stored in the queue. Later, when a thread is available, the Queue will send the message to the Consumer.

    Consumer (MyListener)

    The Queue delivers messages to the Consumer at the consumer's rate. When the Consumer finishes processing a message the Queue will deliver the next available message.

    The Consumer implements javax.jms.MessageListener, and will therefore be identical code in any application server. The Consumer might even be on a different server or use a different application server.

    In this example, the Consumer just logs the message, but more realistic applications might use Java Persistence to store results in a database. The listener instance has full access to Resin-IoC capabilities, including dependency injection, standard aspects like @TransactionAttribute, interceptors, and WebBeans event processing.

    Example: MyListener.java implementation
    package example;
    
    import java.util.logging.Logger;
    import java.util.logging.Level;
    
    import javax.jms.Message;
    import javax.jms.TextMessage;
    import javax.jms.MessageListener;
    
    public class MyListener implements MessageListener {
      private static final Logger log
        = Logger.getLogger(MyListener.class.getName());
    
      public void onMessage(Message message)
      {
        try {
          ObjectMessage objMessage = (ObjectMessage) message;
    
          log.info("received: " + objMessage.getValue());
    
          _lastMessage = textMessage.getValue();
        } catch (Exception e) {
          log.log(Level.WARNING, e.toString(), e);
        }
      }
    }
    

    Configuration

    Since Resin is an inversion of control container (IoC), it can configure the JMS resources in the standard Resin configuration file. The Resin IoC documentation gives more information.

    The configuration is responsible for three things:

    • Configuring the Queue
    • Configuring the MessageListener

    The Queue is configured directly in a <resin:FileQueue> tag, together with any configuration setters. This example uses a local file store.

    Because the listener and sender need a reference to the queue, the jms-queue stores it in the "my_queue" variable.

    Example: Queue configuration in WEB-INF/resin-web.xml
    <web-app xmlns="http://caucho.com/ns/resin"
       xmlns:ee="urn:java:ee"
       xmlns:resin="urn:java:com.caucho.resin">
    
      <resin:FileQueue ee:Named="my_queue">
        <path>WEB-INF/db</path>
      </resin:FileQueue>
    
    </web-app>
    

    JMS also needs a configured ConnectionFactory, so the sender and listener can create JMS connections.

    Example: ConnectionFactory in resin-web.xml
    <web-app xmlns="http://caucho.com/ns/resin"
       xmlns:resin="urn:java:com.caucho.resin">
    
      <resin:JmsConnectionFactory/>
    
    </web-app>
    

    The MessageListener is configured as an EJB message bean. Resin's EJB support instantiates the listeners and receives messages from the queue.

    Example: message bean configuration resin-web.xml
    <web-app xmlns="http://caucho.com/ns/resin">
    
      <resin:FileQueue ee:Named="my_queue">
        <path>WEB-INF/db</path>
      </resin:FileQueue>
    
      <ejb-message-bean class="example.MyListener">
        <destination>${my_queue}</destination>
      </ejb-message-bean>
    
    </web-app>
    

    Demo


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