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 IBM MQ JMS
There are three possible cases, based on the message-driven bean deployment descriptor setting we choose: container-managed transaction (required), container-managed transaction (not supported), and bean-managed transaction.
In the message-driven bean deployment descriptor settings, we 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 we choose container-managed transactions, in the deployment descriptor notebook, we 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. We 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 our 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.
For related information, see the technote "MDB behavior is different on z/OS than on distributed when getting nonpersistent messages within syncpoint" at http://www.ibm.com/support/docview.wss?uid=swg21231549.
- 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, we 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 our 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 our messaging system uses listener ports, we can avoid a poison message scenario by configuring the following property:
For more information about this property, see Listener port settings.
- 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.
If our 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 our messaging system uses the default messaging provider (service integration), configure the following properties on your activation specification to avoid a poison message scenario:
- Automatically stop endpoints on repeated message failure
- We 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 we must have the Automatically stop endpoints on repeated message failure option selected.
For more information on these properties, see JMS activation specification [Settings].
- Delay between failing message retries
- Specify how much time must elapse before a message which has failed to be delivered successfully, is re-delivered.
- If we specify 0 for this parameter there will be no delay before a message is re-delivered.
- To enable this parameter we must have the Automatically stop endpoints on repeated message failure option selected.
If our messaging system uses the IBM MQ messaging provider, configure the following properties on your activation specification to avoid a poison message scenario:
- Stop endpoint if message delivery fails
- We 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.
For more information on these properties, see IBM MQ messaging provider activation specification advanced properties
- 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 we must have the Stop endpoint if message delivery fails option selected.
As an alternative to relying on the application server to stop the listener port or activation specification if a poison message scenario occurs, we can configure IBM MQ to resolve the problem. For queue destinations, specify a backout queue (BOQUEUE), and a backout threshold value (BOTHRESH) on the queue object in IBM MQ. For topic destinations, specify a backout queue (BOQUEUE), and backout threshold value (BOTHRESH) for the IBM MQ system queues SYSTEM.DURABLE.MODEL.QUEUE and SYSTEM.NDURABLE.MODEL.QUEUE. If we do this, IBM MQ handles the poison message. For more information about handling poison messages, see the IBM MQ Use Java section of the IBM MQ library.
Developing an enterprise application to use message-driven beans