2 Replies Latest reply on Feb 16, 2007 5:25 PM by jesse_sweetland

    MDB BMT Redelivery

    jesse_sweetland

      Based on http://www.jboss.com/index.html?module=bb&op=viewtopic&t=53631 it seems that the JMS specification and the EJB specification conflict on how redelivery is handled for MDBs with BMT. Specifically, the EJB specification states that the message acknowledgement is managed by the container (happens outside of the transaction onMessage() method) and can be prevented by throwing a RuntimeException from onMessage(). The JMS specification states that throwing an unchecked exception from onMessage() is not expected and produces undetermined results. Based on my experience with JBoss, it seems that the latter behavior is what is implemented; when I throw a RuntimeException from onMessage the exception is logged but the message is still acknowledged. I've tried in JBoss 4.0.3SP1 and 4.0.5GA.

      I've also read that using BMT with an MDB and expecting redelivery is an anti-pattern, and in most cases I can see that. However, I have a need to log (and commit) events to a database as they occur with the possibility of redelivering the message should processing fail at some point. CMT will not work, since rolling back the distributed JTA transaction will undo the logging. BMT works well, but I cannot force redelivery.

      In the post I linked to there was mention of a possible patch to allow RuntimeExceptions thrown from onMessage() to cause redelivery of messages. Has this patch been applied? If so, is it included with any current version of JBoss AS, or would I need to update the JBoss messaging libraries myself? What sort of configuration changes would I need to make to enable it?

      If the patch hasn't been applied, can anyone suggest a workaround? Some ideas that I have brewing are perhaps using raw JDBC calls (perhaps through a custom Log4J appender) or trying to log in another thread. I'm not certain that either will work as expected, though.

      Any ideas are very much appreciated.

      Thanks,

      Jesse

        • 1. Re: MDB BMT Redelivery
          genman

          My advice to you, having dealt with similar problems myself, would to do one of the following:

          1. Use CMT. In the case you want to log and then redeliver, you can simply copy the message and put it back on the queue. Acknowledge the original message.

          2. Use CMT. Send a non-transactional message to another JMS queue (say your logging q) and process using a MDB in its own CMT as well. Rollback the original message.

          • 2. Re: MDB BMT Redelivery
            jesse_sweetland

            Thanks for your suggestions. I hadn't thought about setting up a queue purely for logging, but that lead me to another solution. I ended creating a session bean for logging and configuring it for CMT with transaction attribute RequiresNew on all of its methods. I then looked up the session bean from my MDB and invoked the logging methods. Using the session bean allows me to serialize the logging calls so that I know immediately whether they succeeded (and aren't lost on some queue somewhere). It's a little kludgy but it seems to work.