How did JMS implement redelivery function of onMessage? - jms

As we known, if there is any exception is thrown at onMessage method of MessageListener, the JMS will try to consume that message again, which called "Redelivery".
But what I'm curious is how did it implement this feature? How did onMessage methods know if there is any exception is thrown? I know the answer may be a basic java knowledge. But unfortunately, I still have no idea on it.
So... is there anyone can clarify it?

This is specific to a particular JMS provider. But if your onMessage() method throws an exception, the code of the JMS provider that calls your onMessage() can just catch it, .e.g
try {
listener.onMessage(..);
} catch (Exception ex) {
//handle exception
}
And if an exception is caught, it can employ a strategy for redelivering the message. The client could send a message back to the JMS broker telling the broker that message delivery failed, and let the broker re-deliver that message.

Related

Throwing exception outside of Flux/Mono reactive pipeline

In my spring JMS listener onMessage method, I am using a reactive pipeline as as below where I receive a JMS message from a queue and transform that to a different format and publishing to another topic. Without the reactive flow, in the case of failure in output publishing, I can throw a runtimeexception for the same message to redeliver from the queue. But by using the below flow of reactive approach, I cannot find a way to throw an exception outside. Can you please help on what should be the approach here for throwing the exception outside to get the message redelivered
public void onMessage(Message message) {
Mono.just(message)
.doOnNext(LoggingUtil::logMessage)
.flatMapIterable(messageTransformer::transformToTriggerEvents)
.doOnNext(LoggingUtil::logTriggerEvent)
.doOnNext(triggerEventPublisher::publish)
.subscribe();
}

How to handle Connection Error in Message Driven Beans?

I have a Message Driven Bean listening to MQ Receiver Queue for incoming Messages.
My MDB is implementing MessageListener and overriding OnMessage method, where I can handle any exception related to the received messages.
All the Connection & Queue parameters are in ejb-jar.xml and weblogic-ejb-jar.xml.
So in case of any Connection failure (e.g. MQ is down, I just get Exception in the console).
How should I catch and handle these connection failure related exceptions in MDB? As I have requirement to send Email notifications to Support group in case of such Connection Failures.
I just saw some info about javax.jms.ExceptionListener, but there is no way I could use it for my setup as I don't have direct access to my connectionfactory / connection objects in case of my MDB.

What's the correct exception type to NACK a message using annotation based listener in spring-boot with amqp?

I'm using spring boot with spring-amqp and annotation based listener to consume message from a rabbitmq broker.
I've a spring component which contains a method like this:
#RabbitListener(queues = "tasks")
public void receiveMessage(#Payload Task task) {...}
I'm using the AUTO mode to acknowledge messages after successful execution of receiveMessage(...). If i detect a special error, i'm throwing AmqpRejectAndDontRequeueException to get this message into a configured dead letter queue. Now i need to nack a message only, so that the message gets requeued into the main queue of rabbitmq and another consumer has the possibility to work on that message again.
Which exception should i throw for that? I wouldn't like to use channel.basicNack(...) like described here (http://docs.spring.io/spring-integration/reference/html/amqp.html) if possible.
As long as defaultRequeueRejected is true (the default) in the container factory, throwing any exception other than AmqpRejectAndDontRequeueException will cause the message to be rejected and requeued.
The exception must not have a AmqpRejectAndDontRequeueException in its cause chain (the container traverses the causes to ensure there is no such exception).

how to prevent message re-queue within rabbitmq server?

I'm using direct exchange to publish messages to certain queues with routing keys, all configured in rabbit-server not code, I'm consuming messages with spring micro-service then some failures happens within the receiving method, then the message re-queued causing loop, so I'd like to add a policy with rabbit-server to prevent that kind of re-queuing, could it be added as an argument while binding queue with exchange with specific routing key, or it should be a policy ?
On any exception by default spring send nack with requeue "true". If in your spring consumer application you want to send requeue false, then throw the exception "AmqpRejectAndDontRequeueException". So your consumer code should loook something like this :
`void onMessage(){
try{
// Your Code Here
} catch(Exception e){
throw new AmqpRejectAndDontRequeueException();
}
}`

What happens on a JMS queue when onMessage() throws a JMSException?

I'm using Spring 2.5 with my custom class that implements MessageListener. If a JmsException is thrown in my onMessage( ) method, what happens to the state of the queue?
Is the message considered "delivered" by the queue the moment onMessage is called? Or does the JmsException trigger some kind of rollback and the message is re-entered on the queue?
Thanks in advance!
From the JMS 1.1 spec...
4.5.2 Asynchronous Delivery
A client can register an object that implements the JMS MessageListener interface with a MessageConsumer. As messages arrive for the consumer, the provider delivers them by calling the listener’s onMessage method.
It is possible for a listener to throw a RuntimeException; however, this is considered a client programming error. Well-behaved listeners should catch such exceptions and attempt to divert messages causing them to some form of application-specific ‘unprocessable message’ destination.
The result of a listener throwing a RuntimeException depends on the session’s acknowledgment mode.
AUTO_ACKNOWLEDGE or
DUPS_OK_ACKNOWLEDGE - the message
will be immediately redelivered. The
number of times a JMS provider will
redeliver the same message before
giving up is provider-dependent. The
JMSRedelivered message header field
will be set for a message redelivered
under these circumstances.
CLIENT_ACKNOWLEDGE - the next message
for the listener is delivered. If a
client wishes to have the previous
unacknowledged message redelivered,
it must manually recover the session.
Transacted Session - the next message
for the listener is delivered. The
client can either commit or roll back
the session (in other words, a
RuntimeException does not
automatically rollback the session).
JMS providers should flag clients with message listeners that are throwing
RuntimeExceptions as possibly malfunctioning.

Resources