In a previous article, we explored the details of entity beans and how they are used to encapsulate data entities to be accessed by business objects. In this article we will look at message-driven beans and how they can be used to listen for Java Message Service (JMS) messages.
Talk with your MOM
Message-oriented middleware (MOM) is a category of interapplication communication software that presents an asynchronous message-passing model as opposed to a request/response model. Most MOM systems are based around a message queuing system. The primary advantage of a message-oriented communications protocol is the ability to store, route, and resend a message that is to be delivered.
Most MOM systems provide a persistent storage to hold messages until they are successfully transferred. This means that it is not necessary for both the sender and receiver to be connected at the same time. This is useful for dealing with faulty connections, unreliable networks, and timed connections. It also means that if a receiver fails to receive a message for any reason, the sender can continue unaffected, since the messages will be held in the message store and will be transmitted when the receiver reconnects.
MOM systems present two messaging models:
- Point-to-point—This model is based on message stores known as queues. A sender sends a message to a specified queue. A receiver receives messages from the queue. A queue can have multiple senders and receivers, but an individual message can only be delivered to one receiver. If multiple receivers are listening for messages on a queue, the underlying MOM system usually determines which receiver will receive the next message. If no receivers are listening on the queue, messages remain in the queue until a receiver attaches to the queue.
- Publish-Subscribe—This model is based on message stores known as topics. Publishers send messages to a topic. Subscribers retrieve messages from a topic. Unlike the point-to-point model, many subscribers can receive the same message.
The diagram in Figure A illustrates the relationships and interactions for sending a message from one publisher to a topic where multiple subscribers are registered to receive the message:
|Interactions between a publisher, some subscribers, and a topic|
JMS meets your MOM
An increasingly important requirement of J2EE application systems is their ability to handle asynchronous messages passed from MOM systems. Java provides the Java Message Service (JMS) for handling MOM messages, which is an application programming interface (API) abstraction of common concepts found in all MOM systems. However, JMS does not define wire protocols or message-content formats.
In a publish-and-subscribe messaging model, a producer sends messages to consumers by delivering the message to a single intermediary topic. A message producer is also called a publisher. The publisher acts as a message transmitter to be used to pass messages from a client or server object to the topic.
Listing A illustrates a method called sendRequest which is used by publishers to send map messages to a topic.
You can create your own asynchronous, JMS-enabled, message listener/receiver, which will receive messages from a topic in its onMessage callback, as shown in Listing B.
- The Java Message Service API
- Writing Java Message Service Programs using MQSeries and VisualAge for Java, Enterprise Edition
- Code Camp: Services on Demand Infrastructure
Overview of message-driven beans
A message-driven bean (MDB) is an EJB that functions as a JMS message consumer. Unlike session beans or entity beans, clients cannot access message-driven beans directly. Also, unlike session beans and entity beans, a message-driven bean does not have remote or home interfaces. The only access a client has to a message-driven bean is through a JMS destination (topic or queue) of which the message-driven bean is listening.
A MDB must implement two interfaces:
- javax.jms.MessageListener—This interface defines the onMessage callback method. When a message is put on the queue/topic, the onMessage method of the message-driven bean is called by the EJB container and passed the actual message.
is the EJB interface that contains the EJB lifecycle methods:
ejbCreate()—called by the EJB container when the message-driven bean is created
ejbRemove()—called by the EJB container when the message-driven bean is destroyed or removed from the EJB pool
setMessageDrivenContext(MessageDrivenContext context)—called prior to ejbCreate and passed the message-driven context by the EJB container
The context has runtime information such as transaction data.
The diagram in Figure B illustrates the interactions between a JMS message, a client, a topic, an application server, an EJB container, and message-driven bean instances.
The deployment descriptor
A message-driven bean must declare deployment information about itself in a deployment-descriptor file named ejb-jar-xml. The EJB container handles the duties of subscribing the bean to the topic or connecting it to the queue based on information placed in the deployment descriptor.
- The ejb-jar.xml file contains:
- The fully-qualified class name of the message-driven bean
- A name for the message-driven bean
- The destination type of the bean
- Transaction attributes
- Security information
The following is an example of a typical ejb-jar.xml file:
The message-driven bean implementation
As mentioned before, message-driven beans do not have remote or local interfaces as with session beans and entity beans. Message-driven beans are not located by client classes, and client classes do not directly invoke methods on them. All access to a message-driven bean is through a JMS topic or queue which directs messages at the message-driven bean through the EJB container. The EJB container ultimately passes the JMS message to the message-driven bean through the bean's onMessage method. All message-driven beans must implement the javax.ejb.MessageDrivenBean and javax.jms.MessageListener interfaces, as the example in Listing C illustrates.