6.2 Message-Driven Bean Concepts

Message-driven beans are EJB components that process asynchronous messages. These messages may be delivered via JMS or by using any other messaging system, such as the Java™ API for XML Messaging (JAX-M). Message-driven beans asynchronously consume messages from a message destination, such as a JMS queue or topic.

Message-driven beans are components that receive incoming enterprise messages from a messaging provider. The primary responsibility of a message-driven bean is to process messages, because the bean's container automatically manages other aspects of the message-driven bean's environment. Message-driven beans contain business logic for handling received messages. A message-driven bean's business logic may key off the contents of the received message or may be driven by the mere fact of receiving the message. Its business logic may include such operations as initiating a step in a workflow, doing some computation, or sending a message.

A message-driven bean is essentially application code that is invoked when a message arrives at a particular destination. With this type of messaging, an application either a J2EE component or an external enterprise messaging client acts as a message producer and sends a message that is delivered to a message destination. The container activates an instance of the correct type of message-driven bean from its pool of message-driven beans, and the bean instance consumes the message from the message destination. Because a message-driven bean is stateless, any instance of the matching type of message-driven bean can process any message. Thus, message-driven beans are programmed in a similar manner as stateless session beans.

The advantage of message-driven beans is that they allow a loose coupling between the message producer and the message consumer, thus reducing the dependencies between separate components. In addition, the EJB container handles the setup tasks required for asynchronous messaging, such as registering the bean as a message listener, acknowledging message delivery, handling re-deliveries in case of exceptions, and so forth. A component other than a message-driven bean would otherwise have to perform these low-level tasks.

6.2.1 Implementing a Message-Driven Bean

To a bean developer, message-driven beans are much like stateless session beans, having the same life cycle as stateless session beans but not having a component or home interface. The implementation class for a message-driven bean must implement the javax.ejb.MessageDrivenBean interface. A message-driven bean class must also implement an ejbCreate method, even though the bean has no home interface. Because they do not expose a component or home interface, clients cannot directly access message-driven beans. Like session beans, message-driven beans may be used to drive workflow processes. However, the arrival of a particular message initiates the process.

Implementing a message-driven bean is fairly straightforward. A message-driven bean extends two interfaces: javax.ejb.MessageDrivenBean and a message listener interface corresponding to the specific messaging system. (For example, when using the JMS messaging system, the bean extends the javax.jms.MessageListener interface.) The container uses the MessageDrivenBean methods ejbCreate, ejbRemove, and setMessageDrivenContext to control the life cycle of the message-driven bean.

You can provide an empty implementation of the ejbCreate and setMessageDrivenContext methods. These methods are typically used to look up objects from the bean's JNDI environment, such as references to other beans and resource references. If the message-driven bean sends messages or receives synchronous communication from another destination, you use the ejbCreate method to look up the JMS connection factories and destinations and to create the JMS connection. The implementation of the ejbRemove method can also be left empty. However, if the ejbCreate method obtained any resources, such as a JMS connection, you should use the ejbRemove method to close those resources.

The methods of the message listener interface are the principal methods of interest to the developer. These methods contain the business logic that the bean executes upon receipt of a message. The EJB container invokes these methods defined on the message-driven bean class when a message arrives for the bean to service.

A developer decides how a message-driven bean should handle a particular message and codes this logic into the listener methods. For example, the message-driven bean might simply pass the message to another enterprise bean component via a synchronous method invocation, send the message to another message destination, or perform some business logic to handle the message itself and update a database.

A message-driven bean can be associated with configuration properties that are specific to the messaging system it uses. A developer can use the bean's XML deployment descriptor to include the property names and values that the container can use when connecting the bean with its messaging system.

6.2.2 JMS and Message-Driven Beans

The EJB architecture requires the container to support message-driven beans that can receive JMS messages. You can think of message-driven beans as message listeners that consume messages from a JMS destination. A JMS destination may be a queue or a topic. When the destination is a queue, there is only one message producer, or sender, and one message consumer. When the destination is a topic, a message producer publishes messages to the topic, and any number of consumers may consume the topic's messages.

A message-driven bean that consumes JMS messages needs to implement the javax.jms.MessageListener interface, which contains the single method onMessage that takes a JMS message as a parameter. When a message arrives for the bean to service, the container invokes the onMessage method defined on the message-driven bean class. The onMessage method contains the business logic that the message-driven bean executes upon receipt of a message. The bean typically examines the message and executes the actions necessary to process it. This may include invoking other components.

The onMessage method has one parameter, the JMS message itself, and this parameter may be any valid JMS message type. The method tests whether the message is the expected type, such as a JMS TextMessage type, and then casts the message to that type and extracts from the message the information it needs.

Because the method does not include a throws clause, no application exceptions may be thrown during processing.

The EJB architecture defines several configuration properties for JMS-based message-driven beans. These properties allow the container to appropriately configure the bean and link it to the JMS message provider during deployment. These properties include the following:

  • destinationType Either a javax.jms.Queue if the bean is to receive messages from a JMS queue, or a javax.jms.Topic if the bean is to receive messages from a JMS topic.

  • subscriptionDurability Used for JMS topics to indicate whether the bean is to receive messages from a durable or a nondurable subscription. A durable subscription has the advantage of receiving a message even if the EJB server is temporarily offline.

  • acknowledgeMode When message-driven beans use bean-managed transactions, this property indicates to the container how to acknowledge the delivery of JMS messages. (When beans use container-managed transactions, the message is acknowledged when the transaction commits.) Its values may be Auto-acknowledge, which is the default, or Dups-ok-acknowledge. The Auto-acknowledge mode indicates that the container should acknowledge messages as soon as the onMessage method returns. The Dups-ok-acknowledge mode indicates that the container may lazily acknowledge messages, which could cause duplicate messages to be delivered.

  • messageSelector Allows a developer to provide a JMS message selector expression to filter messages in the queue or topic. Using a message selector expression ensures that only messages that satisfy the selector are delivered to the bean.

6.2.3 Message-Driven Beans and Transactions

Because messaging systems often have full-fledged transactional capabilities, message consumption can be grouped into a single transaction with such other transactional work as database access. This means that a bean developer can choose to make a message-driven bean invocation part of a transaction. Keep in mind, however, that if the message-driven bean participates in a transaction, you must also be using container-managed transaction demarcation. The deployment descriptor transaction attribute, which for a message-driven bean can be either Required or NotSupported, determines whether the bean participates in a transaction.

When a message-driven bean's transaction attribute is set to Required, the message delivery from the message destination to the message-driven bean is part of the subsequent transactional work undertaken by the bean. By having the message-driven bean be part of a transaction, you ensure that message delivery takes place. If the subsequent transaction fails, the message delivery is rolled back along with the other transactional work. The message remains available in the message destination until picked up by another message-driven bean instance. Note that the message sender and the message receiver, which is the message-driven bean, do not share the same transaction. Thus, the sender and the receiver communicate in a loosely coupled but reliable manner.

If the message-driven bean's transactional attribute is NotSupported, it consumes the message outside of any subsequent transactional work. Should that transaction not complete, the message is still considered consumed and will be lost.

It is also possible to use bean-managed transaction demarcation with a message-driven bean. With bean-managed transaction demarcation, however, the message delivery is not part of the transaction, because the transaction starts within the onMessage method.

6.2.4 Message-Driven Bean Usage

Bean developers should consider using message-driven beans under certain circumstances:

  • To have messages automatically delivered

  • To implement asynchronous messaging

  • To integrate applications in a loosely coupled but reliable manner

  • To have message delivery drive other events in the system workflow

  • To create message selectors, whereby specific messages serve as triggers for subsequent actions



Applying Enterprise Javabeans
Applying Enterprise JavaBeans(TM): Component-Based Development for the J2EE(TM) Platform
ISBN: 0201702673
EAN: 2147483647
Year: 2003
Pages: 110

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net