Search code examples
javajakarta-eejmsmessage-driven-bean

MessageDriverBean - Retry mechanism


I've been reading around SO and some other google results and I got confused, some say I've to call context.setRollbackOnly(); other say it is not required as the MDB will do it by himself.

So, I've a MessageDrivenBean class that receives messages from a JMS Queue.

@MessageDriven(name = "MyEventReceiverJMS", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "jms/TheQueue"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge")
})
public class MyEventReceiverJMS implements MessageListener {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private MessageDrivenContext context;


    @Override
    public void onMessage(Message message) {

        try {
            // Some logic goes here
        } 
        catch (JMSException ex) {
            logger.error("JMSException|could not retrieve object from the message body - reason: {}", ex.getMessage());
            context.setRollbackOnly();
        } 
        catch (JSONException ex) {
            logger.error("error while creating the JSON - reason: ", ex.getMessage());
            context.setRollbackOnly();
        } 
        catch (IOException ex) {
            logger.error("could not communicate with the server - reason: {}", ex.getMessage());
            context.setRollbackOnly();
        }
    }
}

My question is, if there is an exception on the onMessage will the message (or as I call them, event) be put back on the Queue by the MDB or do I have to call context.setRollbackOnly(); on every catch to put the message back?


Solution

  • Do I have to call context.setRollbackOnly() on every catch to put the message back ?

    It is up to us, If you want to roll back the message for all exceptions, yes. If it is a bad/poison message, there is no meaning of rolling back the transaction, it is good idea to discard by logging exception and the payload of the message.

    For your first query, If there is an exception on the onMessage will the message be put back on the Queue, please find the points below:

    The JMS Server could redeliver messages because of:

    A java.lang.Error or java.lang.RuntimeException has been thrown from the Receiver/MDB’s onMessage method

    User has made a call to ejbcontext.setRollbackOnly() in his MDB’s onMessage method (this applies to Container Managed Transaction only)

    MDB participating in a Transaction failed for some reason.

    The below posts are really good and you can refer it for more details:

    http://weblogic-wonders.com/weblogic/2011/01/10/working-with-jms-and-the-standard-issues-in-jms/