Previous Contents Index Next |
Sun Java System Application Server Standard and Enterprise Edition 7 2004Q2 Developer's Guide to Enterprise JavaBeans Technology

> ## Chapter 5
> Using Message-Driven Beans

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

> Note | If you are unfamiliar with message-driven beans or the EJB technology, refer to the Java Software tutorials: http://java.sun.com/j2ee/docs.html 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 Java System Application Server is contained in Sun Java System Application Server and Enterprise JavaBeans Technology and the Sun Java System Application Server Product Introduction.

> This section contains the following topics:

> - About Message-Driven Beans
> - Developing Message-Driven Beans
> - Restrictions and Optimizations
> - Sample Message-Driven Bean XML Files

> ##

> 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
> - Message-Driven Bean Characteristics
> - Transaction Management
> - Concurrent Message Processing

> ### 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:

> - A message-driven bean's instances retain no data or conversational state for a specific client.
> - All instances of a message-driven bean are equal, allowing the container to pool these message-driven bean instances. This allows streams of messages to be processed concurrently.
> - A single message-driven bean can process messages from multiple clients.

> 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 Java System Application Server resources.

> Message-driven beans have the following characteristics:

> - Execute upon receipt of a single client message.
> - Are asynchronously invoked.
> - Are relatively short lived.
> - Do not represent directly shared data in the database, but may access and update this data.
> - Can be transaction-aware.
> - Are stateless.

> ### 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” on page 149 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
> - Configuration

> ### 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 class must implement, directly or indirectly, the javax.ejb.MessageDrivenBean interface.
> - The class must implement, directly or indirectly, the javax.ejb.MessageListener interface.
> - The class must be defined as public and must not be defined as abstract or final.
> - The class must have a public constructor that takes no arguments (used by the container to create instances of the message-driven bean class).
> - The class must not define the finalize method.
> - The class must implement the onMessage method.
> - The class must implement one ejbCreate method, with no arguments.
> - The class must implement one ejbRemove method with no arguments.

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

> - Using ejbCreate
> - Using setMessageDrivenContext
> - Using onMessage
> - Using ejbRemove

> #### Using ejbCreate

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

> - The method name must be ejbCreate.
> - The method must be declared as public and must not be declared as final or static.
> - The return type must be void.
> - The method must have no arguments.
> - The throws clause must not define any application exceptions.

> #### 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 method must be declared as public and must not be declared as final or static.
> - The return type must be void.
> - The method must have a single argument of type javax.jms.Message.
> - The throws clause must not define any application exceptions. Refer to onMessage Runtime Exception for semantics on throwing an exception from onMessage.

> 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 method name must be ejbRemove.
> - The method must be declared as public and must not be declared as final or static.
> - The return type must be void.
> - The method must have no arguments.
> - The throws clause must not define any application exceptions.

> Note | You cannot assume that the container will always invoke the ejbRemove method on a message-driven bean instance.

> 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
> - Message-Driven Bean Pool
> - Server instance-wide Attributes
> - Automatic Reconnection to JMS Provider

> #### 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 Java System 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 Java System 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 Java System Message Queue. Refer to the Sun Java System 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 Java System Application Server-specific bean deployment descriptor contains the elements that define the pool (that is, the bean-pool element):

> - steady-pool-size
> - resize-quantity
> - max-pool-size
> - pool-idle-timeout-in-seconds

> For information on these elements, refer to “Pooling and Caching Elements” on page 208.

> #### 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:

> - steady-pool-size
> - pool-resize-quantity
> - max-pool-size
> - idle-timeout-in-seconds
> - log-level
> - monitoring-enabled

> For further explanation on these attributes, refer to “Pooling and Caching Elements” on page 208 and the Sun Java System Application Server Administrator’s Configuration File Reference.

> For information on monitoring message-driven beans, see the Sun Java System Application Server Administration interface online help and Administration 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 Java System 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 Java System 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
> - Pool Tuning and Monitoring
> - onMessage Runtime Exception

> ### JMS Limitation

> The Sun Java System Application Server supports JMS messaging through a built-in JMS service provided by Sun Java System Message Queue 3.5, Platform Edition. As a standalone product, Sun Java System Message Queue 3.5 supports the JMS 1.1 specification. However, Sun Java System Application Server 7.1 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 Java System Application Server 7.1.

> Developers of JMS messaging applications should, therefore, limit JMS client components that run in a Sun Java System Application Server environment to JMS 1.02b. For more information, see the Sun Java System 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 Java System 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 Java System Application Server Administration 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:

> - If the bean method encounters a runtime exception or error, it should simply propagate the error from the bean method to the container.
> - If the bean method performs an operation that results in a checked exception that the bean method cannot recover, the bean method should throw the javax.ejb.EJBException that wraps the original exception.
> - Any other unexpected error conditions should be reported using javax.ejb.EJBException (javax.ejb.EJBException is a subclass of java.lang.RuntimeException).

> 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 Java System 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:

> - Sample ejb-jar.xml File
> - Sample sun-ejb-jar.xml File

> For information on the elements associated with message-driven beans, refer to “Elements in the sun-ejb-jar.xml File” on page 181 and the Sun Java System 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” on page 181.

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

> <!DOCTYPE sun-ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Sun ONE Application Server 7.1 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 2004 Sun Microsystems, Inc. All rights reserved.