Message redelivery failing for BMT MDBs
tmjkeeney Aug 31, 2004 4:17 PMI am running BMT MDBs under JBoss 3.2.3 using the JBossMQ Provider and have noticed a problem with BMT MDBs failing to redeliver JMS messages when the MDB throws a system exception, a condition that violates the EJB spec section 18.3.3. I have created a patch for the problem and tested it with both BMT and CMT MDBs (After patching the code, any system exception will force redelivery until max retries, then the message goes to the DLQ). Before I apply this patch to my production codebase, I wanted to confirm with the JBoss developers if this is an appropriate solution that will not impact other parts of the system.
I tracked the message redelivery failure for BMT MDBs to the exception handler for the code block beginning on line 1100 in the JMSContainerInvoker.onMessage() method:
try { Transaction tx = tm.getTransaction(); // DLQHandling if (useDLQ && // Is Dead Letter Queue used at all message.getJMSRedelivered() && // Was message resent dlqHandler.handleRedeliveredMessage(message, tx)) //Did the DLQ handler take care of the message { // Message will be placed on Dead Letter Queue, // if redelivered to many times return; } invoker.invoke(id, // Object id - where used? ON_MESSAGE, // Method to invoke new Object[]{message}, // argument tx, // Transaction null, // Principal null); // Cred } catch (Exception e) { log.error("Exception in JMSCI message listener", e); }
If you modify the exception handler to rethrow any system exceptions, the StdServerSession can set the transaction for rollback. So here's the patch:
try { Transaction tx = tm.getTransaction(); // DLQHandling if (useDLQ && // Is Dead Letter Queue used at all message.getJMSRedelivered() && // Was message resent dlqHandler.handleRedeliveredMessage(message, tx)) //Did the DLQ handler take care of the message { // Message will be placed on Dead Letter Queue, // if redelivered to many times return; } invoker.invoke(id, // Object id - where used? ON_MESSAGE, // Method to invoke new Object[]{message}, // argument tx, // Transaction null, // Principal null); // Cred } catch (Exception e) { log.error("Exception in JMSCI message listener", e); > // rethrow system exceptions as an EJBException > if (e instanceof RuntimeException || e instanceof RemoteException) { > throw new EJBException("Encountered system exception.", e); > } }
As said above, this patch works fine for CMT and BMT MDBs. The only problem I see is that CMT MDBs will setRollbackOnly twice: once in the AbstractInterceptor.invokeNext() method, line 105, and once in the StdServerSession.onMessage(), line 275. This could be fixed by wrapping line 275 in StdServerSession with a check to see if the transaction Status is already STATUS_MARKED_ROLLBACK. Correct?
Any comments on the problem/solution would be much appreciated!
Thanks in advance.
--Tom