9.2. Developing a Message-Driven Bean

The MDB class must implement the javax.jms.MessageListener and the javax.ejb.MessageDrivenBean interfaces. In addition to the onMessage method, the following must be implemented:

The following is an example of an MDB class:

public class MdbBean  implements MessageDrivenBean, MessageListener {   

    private transient MessageDrivenContext mdbContext;

    public MdbBean() {}

    public void setMessageDrivenContext(MessageDrivenContext ctx) {
        mdbContext = ctx;
    } 

    public void ejbRemove() {}

    public void ejbCreate() {}

    public void onMessage(Message message) {
        try {
            TextMessage mess = (TextMessage)message;
            System.out.println( "Message received: "+mess.getText());
        }catch(JMSException ex){
            System.err.println("Exception caught: "+ex);
        }
    }
}

The destination associated with an MDB is specified in the deployment descriptor of the bean. A destination is a JMS-administered object, accessible via JNDI (the Java Naming and Directory Interface). The description of an MDB in the EJB 2.1 deployment descriptor contains the following elements, which are specific to MDBs:

The following example illustrates such a deployment descriptor:

<enterprise-beans>
  <message-driven>
    <description>Describe here the message driven bean Mdb</description>
    <display-name>Message Driven Bean Mdb</display-name>
    <ejb-name>Mdb</ejb-name>
    <ejb-class>samplemdb.MdbBean</ejb-class>
    <transaction-type>Container</transaction-type>
    <message-selector>Weight >= 60.00 AND LName 
      LIKE 'Sm_th'</message-selector>
    <message-driven-destination>
      <destination-type>javax.jms.Topic</destination-type>
      <subscription-durability>NonDurable</subscription-durability>
    </message-driven-destination>           
    <acknowledge-mode>Auto-acknowledge</acknowledge-mode>
  </message-driven> 
</enterprise-beans>

If the transaction type is "container," the transactional behavior of the MDB's methods are defined as for other enterprise beans in the deployment descriptor, as in the following example:

<assembly-descriptor>
  <container-transaction>
    <method>
      <ejb-name>Mdb</ejb-name>
      <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
  </container-transaction>
</assembly-descriptor>

For the onMessage method, only the Required or NotSupported transaction attributes must be used, since there can be no pre-existing transaction context.

For the message selector specified in the previous example, the sent JMS messages are expected to have two properties, "Weight" and "LName." For example, to assign the JMS client program sending the messages:

message.setDoubleProperty("Weight",75.5);
message.setStringProperty("LName","Smith");

Such a message will be received by the Message-Driven Bean. The message selector syntax is based on a subset of the SQL92. Only messages whose headers and properties match the selector are delivered. Refer to the JMS specification for more details.

The JNDI name of a destination associated with an MDB is defined in the JOnAS-specific deployment descriptor, within a jonas-message-driven element, as illustrated in the following:

<jonas-message-driven>
  <ejb-name>Mdb</ejb-name>
  <jonas-message-driven-destination>
    <jndi-name>sampleTopic</jndi-name>
  </jonas-message-driven-destination>
</jonas-message-driven>

Once the destination is established, a client application can send messages to the MDB through a destination object obtained via JNDI as follows:

Queue q = context.lookup("sampleTopic");

If the client sending messages to the MDB is an EJB component itself, it is preferable that it use a resource environment reference to obtain the destination object. The use of resource environment references is described in Section 26.2 Writing JMS Operations Within an Application Component.