Inside MessageListener I throw exception. Default behaviour of message listener container is requeue message. My question - is it possible to change message headers when message was requeued?
No, you cannot change a rejected message; you would have to publish a new message after the exception instead of rejecting it.
The framework provides a mechanism to do that using a RepublishMessageRecoverer, adding headers including the stack trace, but it doesn't let you add your own headers; you would need to subclass it to do that.
Related
The use-case is as follows: When user adds a reaction to a message within a thread the Slack bot needs to reply in the same thread.
The problem is that reaction_added event type does not contain the thread_ts which would allow to identify the thread (nor the ts of the root message, which is the same AFAIU).
Is there a way to resolve the thread of the message to which reaction_added was sent to?
The test payloads I tried for that event had
.event.item.ts
and
.event.item.channel
in them.
https://api.slack.com/events/reaction_added
In .NET Framework Microsoft.ServiceBus.Messaging had a class used to receive messages from Service Bus, BrokeredMessage. However, in .NET Standard 2.0, in order to receive messages from a Service Bus, class Message is used, from Microsoft.Azure.ServiceBus.Core.
BrokeredMessage has a method, CompleteAsync(), used to complete the receive operation of a message and indicates that the message should be marked as processed and deleted. I can't find a method for the Message class that does the same thing. Do you guys know any solution in order to mark a message as processed and deleted for the Message class?
To complete the message in the Queue using Microsoft.Azure.ServiceBus.Core, there is a method CompleteAsync available in the QueueClient, through which the messages will be received.
The lock token of the message should be passed as the parameter for the CompleteAsync method.
Example: queueClient.CompleteAsync(message.SystemProperties.LockToken)
Our application is using org.springframework.cloud, spring-cloud-starter-stream-rabbit framework and we are trying to avoid sending specific messages to DLQ and also retrying them, this behaviour should be somehow dynamically, because, for the default messages, retries and DLQ should work.
According to this documentation:
Putting it All Together
And this useful post:
DLX in rabbitmq and spring-rabbitmq - some considerations of rejecting messages
It seems that ImmediateAcknowledgeAmqpException could be used in spring AMQP to mark a message as acknowledged and no further process it. However, when we use this code:
#StreamListener(LogSink.INPUT)
public void handle(Message<Map<String, Object>> message) {
if (message.getPayload().get("condition1").equals("abort")) {
throw new ImmediateAcknowledgeAmqpException("error, we don't want to send this message to DLQ");
}
...
}
The message is always send to DLQ
Our current configuration:
spring.cloud.stream:
bindings:
log:
consumer.concurrency: 10
destination: log
group: myGroup
content-type: application/json
rabbit.bindings:
log:
consumer:
autoBindDlq: true
republishToDlq: true
transacted: true
Are we missing something? Is there any other alternative to avoid publishing to DLQ and requeuing?
republishToDlq does not look at that exception; it only applies when the exception is thrown to the container (method causeChainHasImmediateAcknowledgeAmqpException()).
Republishing subverts that logic since no exception is thrown to the container.
Please open an issue against the Rabbit binder, republishToDlq should honor that exception and discard the failed message.
I have created on replyQ and done biniding with one direct exchange.
Created the message by setting replyto property to "replyQ"
And sending the message on rabbit to the other service.
The service at other end getting the message and sending reply on given replyTo queue.
and now I am trying to read from a replyQ queue using
template.receiveAndConvert(replyQueue));
But getting null response and i can see the message in the replyQ.
That is the service is able to send the reply but am not able to read it from the given queue
Please help what is going wrong.
template.receiveAndConvert() is sync, blocked for some time one time function, where default timeout is:
private static final long DEFAULT_REPLY_TIMEOUT = 5000;
Maybe this one is your problem.
Consider to switch to ListenerContainer for continuous queue polling.
Another option is RabbitTemplate.sendAndReceive(), but yeah, with fixed reply queue you still get deal with ListenerContainer. See Spring AMQP Reference Manual for more info.
I don't know if this could help anyone, but I found out that declaring the expected Object as a parameter of a method listener did the work
#RabbitListener(queues = QUEUE_PRODUCT_NEW)
public void onNewProductListener(ProductDTO productDTO) {
// messagingTemplate.receiveAndConvert(QUEUE_PRODUCT_NEW) this returns null
log.info("A new product was created {}", productDTO);
}
I have two confusions.
1.If RuntimeException thrown from message listener, does SimpleMessageListenrContainer stop?
2.If SimpleMessageListenerContainer not stop, what is behavior about the auto acknowledgement?
Currently, I want that if the message listener handle message failed, i just log the error and don't stop the container meanwhile notify the broker have received message.
Now I just catch the throwable in message listener method, is it the right way?
No, the container won't stop.
If the listener throws an exception, the message is rejected (and requeued by default). You can change the default behavior to discard the message by setting defaultRequeueRejected to false (it's true by default). Or throw an AmqpRejectAndDontRequeueException which instructs the container to reject (and not requeue) the message - the ack is sent as if the listener had thrown no exception.
When a message is rejected without requeuing, it is either discarded or sent to the dead letter exchange, if the queue is so configured.