Introduction to Message-Driven Beans


02 Oct 2020  Sergio Martin Rubio  3 mins read.

A MDB (Message-Driven Bean) is a bean used by JMS to listen to new asynchronous messages. In the same way as any other Java EE enterprise bean, the EJB container in which the MDB runs takes care of the bean lifecycle so you do not have to configure a listener by yourself and add all the required boilerplate.

The main difference between regular session beans and MDBs is that clients don’t access message-driven beans through interfaces, instead MDBs are listening to messages published by a JMS application.

MDB Class

MDBs are regular Java classes that implement javax.jms.MessageListener and are annotated with @MessageDriven. The MessageListener requires that you implement the onMessage() method that is invoked when a message arrives, so we can process the message. You will have to cast the message to one of the five JMS message types (BytesMessage, MapMessage, ObjectMessage, StreamMessage, TextMessage).

Messages are delivered in a transaction context, in other words, if for some reason an exception is thrown, the message will be redelivered.

Message-driven bean classes allow you to set configuration properties to specify things like destination name and destination type. You can define a @ActivationConfigProperty as a value of the parameter activationConfig that is accepted by @MessageDriven to set destination and destinationType . i.e.

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "myQueue"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class MyMessageDrivenBean implements MessageListener {

    private static final Logger LOGGER = Logger.getLogger(MyMessageDrivenBean.class.getName());

    @Override
    public void onMessage(Message message) {
        TextMessage textMessage = (TextMessage) message;

        try {
            LOGGER.info("Message received: " + textMessage.getText());
        } catch (JMSException e) {
            LOGGER.severe("Something went wrong when consuming message: " + e.getMessage());
        }
    }
}

The destination type can also be a topic if you specify as the property value javax.jms.Topic.

Other Configuration Properties

Property Name Property Value Description
acknowledgeMode AUTO_ACKNOWLEDGE
(default)
An acknowledge message
is sent automatically
acknowledgeMode DUPS_OK_ACKNOWLEDGE An acknowledgment message
is not sent to the client right away.
This is good for performance.
subscriptionDurability NonDurable
(default)
If nobody is listening to
the topic the message is missed
subscriptionDurability Durable Ensures that messages sent to
a topic are not missed

Acknowledgment for an MDB is managed by the container, so only the two automatic modes above apply — CLIENT_ACKNOWLEDGE is not a valid acknowledgeMode for a message-driven bean.

Lifecycle Callbacks and Interceptors

MDBs are compatible with enterprise bean lifecycle methods:

  • @PostConstruct: the method is invoked before the first message is received by the MDB.
  • @PreDestroy: the method is invoked when the MDB is removed from the pool or destroyed.

Interceptors are also allowed. We can define our interceptor as a method annotated with @AroundInvoke. These methods will be invoked before and after the execution of the onMessage() method.

Examples

Image by Antonios Ntoumas from Pixabay