Message-driven beans - transaction support

Message-driven beans can handle messages on destinations (or endpoints) within the scope of a transaction.

Transaction handling when using the Message Listener Service with WebSphere MQ JMS

There are three possible cases, based on the message-driven bean deployment descriptor setting you choose: container-managed transaction (required), container-managed transaction (not supported), and bean-managed transaction.

In the message-driven bean deployment descriptor settings, you can choose whether the message-driven bean manages its own transactions (bean-managed transaction), or whether a container manages transactions on behalf of the message-driven bean (container-managed transaction). If you choose container-managed transactions, in the deployment descriptor notebook, you can select a container transaction type for each method of the bean to determine whether container transactions are required or not supported. The default container transaction type is required.

Container-managed transaction (required)

In this case, the application server starts a global transaction before it reads any incoming message from the destination, and before the onMessage() method of the message-driven bean is invoked by the application server. This means that other EJBs that are invoked in turn by the message, and interactions with resources such as databases can all be scoped inside this single global transaction, within which the incoming message was obtained.

If this application flow completes successfully, the global transaction is committed. If the flow does not complete successfully, (if the transaction is marked for rollback or if a runtime exception occurs), the transaction is rolled back, and the incoming message is rolled back onto the message-driven bean destination.

Container-managed transaction (not supported)

In this case there is no global transaction, but the JMS provider can still deliver a message from a message-driven bean destination to the application server in a unit of work. You can consider this as a local transaction, because it does not involve other resources in its transactional scope.

The application server acknowledges message delivery on successful completion of the onMessage() dispatch of the message-driven bean (using the acknowledgement mode specified by the assembler of the message-driven bean).

However, the application server does not perform an acknowledge, if an unchecked runtime exception is thrown from the onMessage() method. So, does the message roll back onto the message-driven bean destination (or is it acknowledged and deleted)?

The answer depends on whether a syncpoint is used by your JMS provider and can vary depending on the operating platform (in particular the z/OS® operating platform can impart different behavior here).

If your JMS provider establishes a syncpoint around the message-driven bean message consumption in this container-managed transaction (not supported) case, the message is rolled back onto the destination after an unchecked exception.

If a syncpoint is not used, then the message is deleted from the destination after an unchecked exception.

Bean-managed transaction

In this case, the action is similar to the container-managed transaction (not supported) case. Even though there might be a user transaction in this case, any user transaction started within the onMessage dispatch of the message-driven bean does not include consumption of the message from the message-driven bean destination within the transaction scope. To do this, use the container-managed transaction (required) scenario.

Message redelivery

In each of the previous three cases, a message that is rolled back onto the message-driven bean destination is eventually re-dispatched. If the original rollback was due to a temporary system problem, you would expect the re-dispatch of the message-driven bean with this message to succeed on re-dispatch. If, however, the rollback was due to a specific message-related problem, the message would repeatedly be rolled back and re-dispatched. This is known as a poison message scenario.

If your messaging system uses listener ports, the application server handles this scenario, by tracking the frequency with which a specific message is dispatched, and by stopping the associated listener port after a specified number of attempted re-deliveries of that message have occurred.

If your messaging system uses listener ports, you can avoid a poison message scenario by configuring the following property:
Maximum Retries
The Maximum Retries parameter specifies the number of times that the listener tries to deliver a specific message to a message-driven bean instance before the listener is stopped.
If this parameter is set to 0 the listener port will stop after a single failure of a message to be delivered successfully.
For more information about this property, see Listener port settings.

If your messaging system uses activation specifications, the poison message scenario is handled in a slightly different way. Whereas listener ports track the number of times a specific message has failed and been re-delivered, activation specifications count the number of sequential message delivery failures.

If your messaging system uses the default messaging provider (service integration), you must configure the following properties on your activation specification to avoid a poison message scenario:
Automatically stop endpoints on repeated message failure
You must make sure that this option is selected.
This property suspends message delivery to the endpoint when the Sequential failed message threshold is reached.
Sequential failed message threshold
This parameter determines how many message deliveries can fail before message delivery is suspended.
To enable this parameter you must have the Automatically stop endpoints on repeated message failure option selected.
Delay between failing message retries
This parameter specifies how much time must elapse before a message which has failed to be delivered successfully, is re-delivered.
If you specify 0 for this parameter there will be no delay before a message is re-delivered.
To enable this parameter you must have the Automatically stop endpoints on repeated message failure option selected.
For more information on these properties, see JMS activation specification [Settings].
If your messaging system uses the WebSphere® MQ messaging provider, you must configure the following properties on your activation specification to avoid a poison message scenario:
Stop endpoint if message delivery fails
You must make sure that this option is selected.
This property suspends message delivery to the endpoint when the Number of sequential delivery failures before suspending endpoint is reached.
Number of sequential delivery failures before suspending endpoint
This parameter determines how many message deliveries can fail before message delivery is suspended.
To enable this parameter you must have the Stop endpoint if message delivery fails option selected.
For more information on these properties, see WebSphere MQ messaging provider activation specification advanced properties

As an alternative to relying on your application server to stop the listener port or activation specification if a poison message scenario occurs, you can configure WebSphere MQ to resolve the problem. For queue destinations, specify a backout queue (BOQUEUE), and a backout threshold value (BOTHRESH) on the queue object in WebSphere MQ. For topic destinations, specify a backout queue (BOQUEUE), and backout threshold value (BOTHRESH) for the WebSphere MQ system queues SYSTEM.DURABLE.MODEL.QUEUE and SYSTEM.NDURABLE.MODEL.QUEUE. If you do this, WebSphere MQ handles the poison message. For more information about handling poison messages, see the WebSphere MQ Using Java™ section of the WebSphere MQ library.