4

I am using Default Message Listener Container. I have set session transacted property true in configuration.

My onMessage() method is this:

public void onMessage(Message message) {
    try {
        // Some code here
    } catch (JmsException jmse) {
        log.error(jmse);
    } catch (Throwable t) {
        log.error(t);
    }
}

As you can see I am handling the exception in a catch block.

My requirement is that if it is a JMS Exception, it should be resent, i.e. message redelivered to the listener/consumer as it happens when there is transaction rollback. How can that happen?

Can we manually rollback the transaction here? I think that is a possible solution but I dont how to do that in code.

Another generic question:

Since I am handling all the possible exceptions through a catch block, I guess there will not be a scenario of message redelivery i.e. transaction rollback since I am handling all the possible exceptions through the catch block. Am I right?

Antti29
  • 2,953
  • 12
  • 34
  • 36
africandrogba
  • 334
  • 1
  • 3
  • 21

2 Answers2

5

You don't need a SessionAwareMessageListener; simply throw the exception instead of catching it and the container will rollback the delivery.

Specifically, it will rollback if the exception is a JmsException, RuntimeException (or subclasses) or an Error.

You should generally not catch Throwable anyway; it's not good practice.

EDIT

public void onMessage(Message message) {
    try {
        // Some code here
    } 
    catch (JmsException jmse) {
        log.error(jmse);
        // Do some stuff
        throw new RuntimeException(jmse); // JMSException is checked so can't throw
    }
    catch (RuntimeException e) {
        log.error(e);
        throw e;
    }
    catch (Exception e) {
        log.error(t);
        throw new RuntimeException(e);
    }
}
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Since I am using Throwable to catch, doesnt it catch every possible exception since throwable is the parent class of all exceptions and errors. – africandrogba Sep 29 '17 at 14:11
  • Yes, but it's not a good idea to "eat" `Throwable` - it could be an `Error` such as OOM. In any case, to force a rollback you'll have to wrap the `Throwable` in a `RuntimeException` because you can't re-throw it because the method signature doesn't allow it. – Gary Russell Sep 29 '17 at 14:12
  • Can you demonstrate through code? I dont know how to implement what you are saying in code. – africandrogba Sep 29 '17 at 14:13
  • I have some logic in JMS exception block which needs to be executed before the rollback. Would your suggestion be still valid then? – africandrogba Sep 29 '17 at 14:19
  • See the edit; the rollback doesn't happen until the exception is thrown. – Gary Russell Sep 29 '17 at 14:36
  • So I believe this will handle the logic and after that it will start a rollback and the message will be redelivered. Can you look at this question too regarding durable subscription https://stackoverflow.com/questions/46490934/use-case-scenario-of-durable-listeners-consumers – africandrogba Sep 29 '17 at 14:40
0

Have you tried SessionAwareMessageListener ? Please check here

L.H
  • 81
  • 6
  • What does it do ? So currently my class implements message listener, now it has to implement sessionawaremessagelistener, right? – africandrogba Sep 29 '17 at 05:46
  • Also I have to acknowledge manually through session object and call a rollback in catch block through session object when necessary. I believe this is how you are saying I should implement it. – africandrogba Sep 29 '17 at 05:47
  • since you get a session object here in this interface you can rollback or commit the transactions as per your requirement. – L.H Sep 29 '17 at 06:12