Sun ONE logo      Previous      Contents      Index      Next     

Sun ONE Application Server 7 Developer's Guide to Enterprise Java Beans Technology

Chapter 5
Using Message-Driven Beans

This section describes message-driven beans and explains the requirements for creating them in the Sun ONE Application Server 7 environment.


Note

If you are unfamiliar with message-driven beans or the EJB technology, refer to the Java Software tutorials:

Extensive information on message-driven beans is contained in chapters 15 and 16 of the Enterprise JavaBeans Specification, v2.0.

Overview material on the Sun ONE Application Server is contained in "Introducing the Sun ONE Application Server Enterprise JavaBeans Technology" and the Sun ONE Application Server Product Introduction.


This section contains the following topics:


About Message-Driven Beans

A message-driven bean is an enterprise bean that allows J2EE applications to process messages asynchronously. It acts as message listener, which is similar to an event listener except that it receives messages instead of events. The messages may be sent by any J2EE component—an application client, another enterprise bean, or a web component—or by an application or system that does not use J2EE technology.

The following topics are addressed in this section:

Message-Driven Beans Differences

Session beans and entity beans allow you to send JMS messages and to receive them synchronously, but not asynchronously. To avoid tying up server resources, you may prefer to use asynchronous receives in a server-side component. To receive messages asynchronously, use a message-driven bean.

The most visible difference between message-driven beans and session and entity beans is that clients do not access message-driven beans through interfaces. Unlike a session or entity bean, a message-driven bean has only a bean class.

In several respects, a message-driven bean resembles a stateless session bean:

The instance variables of the message-driven bean instance can contain some state across the handling of client messages—for example, a JMS connection, an open database connection, or an object reference to an EJB object.

Message-Driven Bean Characteristics

A message-driven bean instance is an instance of a message-driven bean class. It has neither a home nor a remote interface; message-driven beans are anonymous. They have no client-visible identity.

A client accesses a message-driven bean through JMS by sending messages to the message destination for which the message-driven bean class is the MessageListener. A message-driven bean's Queue and Topic are assigned during deployment using the Sun ONE Application Server resources.

Message-driven beans have the following characteristics:

Transaction Management

Both container-managed and bean-managed transactions as defined in the Enterprise JavaBeans Specification, v2.0 are supported.

With container-managed transactions, a message may be delivered to a message-driven bean within a transaction context, so that all operations within the onMessage method are part of a single transaction. If message processing is rolled back, the message will be redelivered.

Refer to "Handling Transactions with Enterprise Beans" for additional information on transactions.

Concurrent Message Processing

A container allows many instances of a message-driven bean class to be running concurrently, thus allowing for the concurrent processing of a stream of messages. No guarantees are made as to the exact order in which messages are delivered to the instances of the message-driven bean class, although the container attempts to deliver messages in chronological order when this does not impair the concurrency of message processing.

Message-driven beans should, therefore, be prepared to handle messages that are out of sequence. For example, a message to cancel a reservation may be delivered before the message to make the reservation.


Developing Message-Driven Beans

The goal of the message-driven bean model is to make developing an enterprise bean that is asynchronously invoked to handle incoming messages as simple as developing the same functionality in any other JMS listener. A further goal is to allow for concurrent processing of a stream of messages by means of container-provided pooling of message-driven bean instances.

The following sections provide guidelines on creating message-driven beans:

Creating the Bean Class Definition

Unlike session and entity beans, message-driven beans do not have the remote or local interfaces that define client access. Client components do not locate message-driven beans and invoke methods directly on them.

Although message-driven beans do not have business methods, they may contain helper methods that are invoked internally by the onMessage method.

For message-driven beans, the class requirements are:

The following sections address the various methods in a message-driven bean’s class definition.

Using ejbCreate

The message-driven bean class defines one ejbCreate method whose signature must follow these rules:

Using setMessageDrivenContext

The container provides the message-driven bean instance with a MesssageDrivenContext. This gives the message-driven bean instance access to the instance's context maintained by the container.

Using onMessage

The onMessage method has a single argument: the incoming message.

The onMessage method is called by the bean’s container when a message has arrived for the bean to service. This method contains the business logic that handles the processing of the message. It is the message-driven bean's responsibility to parse the message and perform the necessary business logic.

The message-driven bean class defines one onMessage method whose signature must follow these rules:

The onMessage method is invoked in the scope of a transaction that is determined by the transaction attribute specified in the deployment descriptor.


Note

If the bean is specified as using container-managed transaction demarcation, either the Required or NotSupport transaction attribute must be specified in its deployment descriptor.


Using ejbRemove

The message-driven bean class defines one ejbRemove method to free a bean when it is no longer needed. The signature must follow these rules:

The ejbRemove method is not called if the EJB container crashes, or if an exception is thrown from the instance’s onMessage method to the container. If the message-driven bean instance allocates resources in the ejbCreate method, and/or the onMessage method, and releases the resources in the ejbRemove method, these resources will not be automatically released. Your application should provide a mechanism to periodically clean up the unreleased resources.

Configuration

This section addresses the following configuration topics:

Connection Factory and Destination

A message-driven bean is a JMS client. Therefore, the message-driven bean container uses the JMS service integrated into the Sun ONE Application Server. JMS clients use JMS Connection Factory- and Destination-administered objects. A JMS Connection Factory administered object is a resource manager Connection Factory object that is used to create connections to the JMS provider.

The mdb-connection-factory element in the sun-ejb-jar.xmlfile for a message-driven bean can be used to specify the connection factory used by the container to create the container connection to the JMS provider. This element can be used to work with a third-party JMS provider.

If the mdb-connection-factory element is not specified, a default one created at server startup is used. This provides connection to the built-in Sun ONE Message Queue broker on the port that is specified in the jms-service element (if enabled) in the server.xml file, using the default user name/password (resource principal) of the Sun ONE Message Queue. Refer to the Sun ONE Message Queue Developer’s Guide for more information.

The jndi-name element of the ejb element in sun-ejb-jar.xml file specifies the JNDI name of the administered object for the JMS Queue or Topic destination that is associated with the message-driven bean.

Message-Driven Bean Pool

The container manages a pool of message-driven beans for the concurrent processing of a stream of messages. The Sun ONE Application Server-specific bean deployment descriptor contains the elements that define the pool (that is, the bean-pool element):

For information on these elements, refer to "Pooling and Caching Elements".

Server instance-wide Attributes

An administrator can control the following server instance-wide message-driven bean attributes for the mdb-container element in the server.xml file:

For further explanation on these attributes, refer to "Pooling and Caching Elements" and the Sun ONE Application Server Administrator’s Configuration File Reference.

For information on monitoring message-driven beans, see the Sun ONE Application Server Administration interface online help and Administrator’s Guide.


Note

Running monitoring when it is not need may impact performance, so you may choose to turn monitoring off using the asadmin command or the Administration interface when it is not in use.


Automatic Reconnection to JMS Provider

When the Sun ONE Application Server is started, for each deployed message-driven bean, its container keeps a connection to the JMS provider. When the connection is broken, the container is not able to receive messages from the JMS provider and, therefore, is unable to deliver messages to its message-driven bean instances. When the auto reconnection feature is enabled, the container automatically tries to reconnect to the JMS provider if the connection is broken.

The mdb-container element in the server.xml file contains auto reconnection properties. By default, reconnect-enabled is set to true and reconnect-delay-in-seconds is set to 60 seconds. That is, there is a delay of 60 seconds before each attempt to reconnect, and reconnect-max-retries is set to 60.

The container logs messages for each reconnect attempt.


Note

Depending on where the message processing stage is, if the connection is broken, the onMessage method may not be able to complete successfully, or the transaction may be rolled back due to a JMS exception. When the container reestablishes connection to the JMS provider, JMS message redelivery semantics apply.


Refer to the Sun ONE Application Server Administrator’s Configuration File Reference for information on auto reconnect properties of the mdb-container element in the server.xml file.


Restrictions and Optimizations

This section discusses the following restrictions and performance optimizations that you should be aware of in developing message-driven beans:

JMS Limitation

The Sun ONE Application Server supports JMS messaging through a built-in JMS service provided by Sun ONE Message Queue 3.0.1, Platform Edition. As a standalone product, Sun ONE Message Queue 3.0.1 supports the JMS 1.1 specification. However, Sun ONE Application Server 7 supports the J2EE 1.3 specification, which encompasses only the more limited JMS 1.02b specification. For this reason, the additional features embodied in JMS 1.1 are not available to applications running on the Sun ONE Application Server 7.

Developers of JMS messaging applications should, therefore, limit JMS client components that run in a Sun ONE Application Server environment to JMS 1.02b. For more information, see the Sun ONE Message Queue Developer’s Guide or Release Notes.

Pool Tuning and Monitoring

The message-driven bean pool is also a pool of threads, with each message-driven bean instance in the pool associating with a server session, and each server session associating with a thread. Therefore, a large pool size also means a high number of threads, which will impact performance and server resources.

When configuring message-driven bean pool properties, you must consider factors such as message arrival rate and pattern, onMessage method processing time, overall server resources (threads, memory, and so on), and any concurrency requirements and limitations from other resources that the message-driven bean may access.

Performance and resource usage tuning should also consider potential JMS provider properties for the connection factory that is used by the container (mdb-connection-factory element in deployment descriptor). For example, the Sun ONE Message Queue flow control related properties for connection factory should be tuned in situations where the message incoming rate is much higher than max-pool-size can handle.

Refer to the Sun ONE Application Server Administrator’s Guide for information on how to get message-driven bean pool statistics.

onMessage Runtime Exception

Message-driven beans, like other well-behaved JMS MessageListeners, should not, in general, throw runtime exceptions. If a message-driven bean's onMessage method encounters a system-level exception or error that does not allow the method to successfully complete, the Enterprise JavaBeans Specification, v2.0 provides the following guidelines:

Under container-managed transaction demarcation, upon receiving a runtime exception from a message-driven bean's onMessage method, the container will roll back the container-started transaction and JMS message will be redelivered. This is because the message delivery itself is part of the container-started transaction. By default, the Sun ONE Application Server container closes the container's connection to the JMS provider when the first runtime exception is received from a message-driven bean instance's onMessage method. This avoids potential message redelivery looping and protects server resources if the message-driven bean's onMessage method continues misbehaving. This default container behavior can be changed using the cmt-max-runtime-exceptions property of the mdb-container element in the server.xml file.

The cmt-max-runtime-exceptions property specifies the maximum number of runtime exceptions allowed from a message-driven bean's onMessage method before the container starts to close the container's connection to the JMS provider. By default this value is 1; -1 disables this container protection.

A message-driven bean's onMessage method can use the javax.jms.Message getJMSRedelivered method to check whether a received message is a redelivered message.


Note

The cmt-max-runtime-exceptions property may be deprecated in the future.



Sample Message-Driven Bean XML Files

This section includes the following sample files:

For information on the elements associated with message-driven beans, refer to "Elements in the sun-ejb-jar.xml File" and the Sun ONE Application Server Developer’s Guide.

Sample ejb-jar.xml File

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>

<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>MessageBean</ejb-name>
      <ejb-class>samples.mdb.ejb.MessageBean</ejb-class>
      <transaction-type>Container</transaction-type>
      <message-driven-destination>
        <destination-type>javax.jms.Queue</destination-type>
      </message-driven-destination>
      <resource-ref>
        <res-ref-name>jms/QueueConnectionFactory</res-ref-name>
        <res-type>javax.jms.QueueConnectionFactory</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>
    </message-driven>
  </enterprise-beans>
    <assembly-descriptor>
      <container-transaction>
        <method>
          <ejb-name>MessageBean</ejb-name>
          <method-intf>Bean</method-intf>
          <method-name>onMessage</method-name>
          <method-params>
            <method-param>javax.jms.Message</method-param>
          </method-params>
        </method>
      <trans-attribute>NotSupported</trans-attribute>
    </container-transaction>
  </assembly-descriptor
</ejb-jar>

Sample sun-ejb-jar.xml File

For information on these elements, refer to "Elements in the sun-ejb-jar.xml File"

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sun-ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 7.0 EJB 2.0//EN' 'http://www.sun.com/software/sunone/appserver/dtds/sun-ejb-jar_2_0-0.dtd'>

<sun-ejb-jar>
  <enterprise-beans>
    <ejb>
      <ejb-name>MessageBean</ejb-name>
      <jndi-name>jms/sample/Queue</jndi-name>
      <resource-ref>
        <res-ref-name>jms/QueueConnectionFactory</res-ref-name>
        <jndi-name>jms/sample/QueueConnectionFactory</jndi-name>
        <default-resource-principal>
          <name>guest</name>
          <password>guest</password>
        </default-resource-principal>
      </resource-ref>
      <mdb-connection-factory>
        <jndi-name>jms/sample/QueueConnectionFactory</jndi-name>
        <default-resource-principal>
          <name>guest</name>
          <password>guest</password>
        </default-resource-principal>
      </mdb-connection-factory>
    </ejb>
  </enterprise-beans>
</sun-ejb-jar>



Previous      Contents      Index      Next     


Copyright 2003 Sun Microsystems, Inc. All rights reserved.