Back Forum Reply New

Failure to send a message doesn't get reported by an intermediary transformer

Hi!

The beginning of my pipeline looks like this:
-gt; [Input channel (direct)] -gt; [Transformer] -gt; [Priority channel (queue with a limited capacity)] -gt;

When I send a message into the input channel, it never gets reported if the message wasn't actually sent into the priority queue. Sending to the input channel always returns true as the messages get successfully delivered to the transformer. The transformer transforms and then it tries to send into its output channel. And when the priority queue is full, it fails to send but it has no means to report the failure. This seems to happen because the bean standing for the 'transformer' element in the SI name space is a subclass of AbstractReplyProducingMessageHandler and its 'handleMessageInternal' method just tries to send messages to output/reply channels but does nothing if it cannot (even though the internally called 'sendReplyMessage' method actualy does return the result of the call to channel template).

Can the implementation of the AbstractReplyProducingMessageHandler be changed so that it would support maybe what AbstractMessageRouter supports (I mean throwing an exception if 'resolutionRequired')?Code:
if (!sent) {

...
else if (this.resolutionRequired) {
throw new MessageDeliveryException(message,
quot;no channel resolved by router and no default output channel definedquot;);
}
}
I currently save all messages data before sending them into the input channel, so that I can try sending them later again. Just it would be great to be able to track messages that could not get queued so that it was easier to tell which messages need to be re-sent.

That looks like a bug to me. Please create an issue for it.

Created: browse/INT-589

Thank you for reporting this. I have added it to the list for 1.0.2. We may have to push it to 1.0.3 since we are trying to get 1.0.2 out ASAP. However, this is definitely worth trying to squeeze in if possible.

Thanks,
Mark

Thank you!

The slightly tricky part of this is when a handler may be sending multiple reply messages (e.g. Splitter). In other words, the method whose boolean return value is currently being ignored is invoked within a loop:

Code:
for (MessageBuilderlt;?gt; builder : replyMessageHolder.builders()) {   builder.copyHeadersIfAbsent(requestHeaders);   this.sendReplyMessage(builder.build(), replyChannel);
}
Therefore, if 5 messages are being sent and the 3rd one fails, a MessageDeliveryException thrown here would contain that 3rd Message (as the 'failed/undeliverable' message). Meanwhile the first 2 have already been sent, and the last 2 remain unsent.

We could either follow that policy (i.e. report failure immediately) or try to send all messages while keeping track of any that were not sent. In the latter case, we could throw an Exception that contains all unsent Messages. If there is a boolean flag, then we could always have the option of ignoring send failures altogether (might be fine for some use-cases). Of course, this multi-failure problem would not occur in single-reply handlers, and that does include most of them (except Splitter). It might be worth adding support for a collection of failedMessages to the MessageDeliveryException instead of just one. Or, perhaps we could create a subclass of that for MultiMessageDeliveryException... not sure about that one.

Any thoughts?
Thanks,
Mark

I'm personally for the 2nd option -- trying to send all messages and then if some of them didn't get sent throwing an exception somehow detailing the failures (maybe yes -- just a subclass of the MessageDeliveryException containing all messages failed to be sent).
¥
Back Forum Reply New