A message driven bean is simply an 'asynchronous message consumer'. It is invoked by the container when a message is received at the destination that the MDB services. There is no client side visibility or conversational state with MDBs and the lifetime of the MDB instance is totally controlled by the container.
The EJB 3.0 spec states:
A message-driven bean instance has no state for a specific client. However, the instance variables of the message-driven bean instance can contain state across the handling of client messages. Examples of such state include an open database connection and a reference to an enterprise bean.
A further goal of the message-driven bean model is to allow for the concurrent processing of a stream of messages by means of container-provided pooling of message-driven bean instances.
Like a session bean, the EJB3 cartridge generates a message driven bean class which should NOT be modified manually and a corresponding implementation class that requires the business logic for message processing. The MDB class contains all the necessary annotations. The MDB implementation class extends the MDB class.
Currently, EJB3 cartridge does not generate the @MessageDriven metadata annotation in the MDB class. Instead, the ejb-jar.xml and jboss.xml deployment descriptors contain the necessary metadata, due to the design of separation by inheritance where the business logic is separated in the subclass from the auto-generated code in the base class.
The abstract message-driven bean class defines all the business methods as abstract. The message-driven bean implementation class requires the business method implementations. The implementation class also contains the implementation of the onMessage callback in the MessageListener.
The following examples illustrates how the EJB3 cartridge will generate the message-drive bean related classes and the required references in the session bean classes. The PaymentProcessor is the message-driven bean that is servicing the Queue which is located at queue/howtomodel/howto10a. The tagged values used are explained further down.
The dependency from the RentalService session bean to the PaymentProcessor MDB injects the required connection factory and destination objects into the session bean. Similarly, the dependency from the PaymentProcessor MDB to the PaymentService session bean injects the EJB instance of the session bean into the MDB.
For every message-driven bean, you MUST specify the destination type for the servicing MDB. This is achieved by simply modeling the andromda_ejb_mdb_destination_type tagged value on the MDB class. Your options are:
javax.jms.Queue
If you have only ONE listener on a destination, then you specify the destination type as a Queue.
javax.jms.Topic
If you have multiple subscribers on a destination, then you specify the destination as a Topic.
For every message-driven bean, you MUST specify the destination queue or topic name that the MDB is associated with. This is achieved by modeling the andromda_ejb_mdb_destination tagged value.
To specify the acknowledge mode for a JMS message driven bean, simply model the andromda_ejb_mdb_acknowledge_mode tagged value on the class. This only needs to be specified if DUPS_OK_ACKNOWLEDGE mode is required since the default is AUTO_ACKNOWLEDGE.
By specifying a message selector constraint, you can limit the messages that a message-driven bean is configured to received. To set a message selector, simply model the andromda_ejb_mdb_selector tagged value on the MDB class.
You can specify the message-driven bean subscription durability by modeling the andromda_ejb_mdb_subscription_durability tagged value on the MDB class. Queues are always durable by default. The durability only needs to specified on Topics. By default, Topics are non-durable. Your options are:
Message driven beans have lifecycle callback interceptor methods or regular interceptors which can be defined in a separate interceptor class using the EJB3 cartridge. To find out more information on interceptors, click on interceptors. To find out more information on lifecycle callbacks, click on lifecycle callbacks.
Like session beans, message-driven beans can use container-managed or bean-managed transaction demarcation. By default and if unspecified, the container-managed transaction demarcation is adopted. However, you can specify bean-managed transaction demarcation by modeling the andromda_ejb_transaction_management tagged value to BEAN on the message-driven class.
If the MDB is specified using container-managed transaction demarcation, you can specify the transaction attribute type to either:
By default, the EJB3 cartridge will generate the @TransactionAttribute annotation, setting the attribute type to REQUIRED. To override this default value, you can model the andromda_ejb_transaction_type tagged value on the MDB class.
Because message-driven beans lifecycle is totally controlled by the container, a client is NOT calling the onMessage method directly. Therefore, the security identity for the execution of methods in the MDB is controlled via the @RunAs annotation. This can easily be set by following the security howto here.
The EJB3 cartridge injects the MessageDrivenContext into every MDB using the @Resource annotation by default. The MessageDrivenContext instance, named context, provides the following methods:
To inject a session bean into the MDB, model a dependency from the MDB to the destination session bean. As a result, the EJB annotation will be generation on the attribute declaring the injected destination session bean.
To inject an environment entry resource value, model an attribute with classifier scope and set the attribute stereotype to <<EnvEntry>>. The environment entries will be defined in the MDB class and configured in the ejb-jar.xml deployment descriptor. You must define a default value for these attributes in the model. Refer to Environment Entry Injections for further information.
In some circumstance, you need to configure your MDB to maintain a max pool size of 1 such that you have a singleton message driven bean. This can be achieved via the maximum pool size tagged value which is modeled on the MDB.
You also have the option of configuring the minimum pool size of the MDB.
Both tagged values will add the appropriate activation config property to the ejb-jar.xml deployment descriptor.
The EJB3 cartridge will create the default MQ destinations XML descriptor which can be hot deployed to the JBoss container for creating your queues or topics. The following is a very basic example with a single queue mbean definition.
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=EmailSenderMDBBean"> <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> <attribute name="JNDIName">queue/emailSender</attribute> </mbean> <!-- jboss mq destinations merge-point --> </server>
To find out how to inject environment entries to session and message driven beans, click here.