Yes, that's perfect for now.
Thanks a lot, Mark.
Printable View
Yes, that's perfect for now.
Thanks a lot, Mark.
Hi Pierre,
This is exactly what iam doing now and i is going into production on Jan 1st.
I am using Websphere SI bus as default JMSrovider and using Spring integration 2.0.0.RC1 for my standalone consumer app.
I am using Message driven channel adapter.
Logic:
1) Receive a message
2) Process the message and do a http Post to Our customer Url.
3) If step 2 fails, throw an exception. This way the message is retained in my JMS provider. In JMs provider there is a setting for On exception to block it for xxx millisecs. I am blocking it for 30 minutes before it is sent to My Standalone spring integration app.
I am using deliveryCount in the message header as my retry count for my application logic. If retry fails for 6th time, i redirect the message to a different Queue destination on websphere SI Bus for further processing.
so, you could do that, if your jms provider gives you the option for on exception handling.
Hope this helps.
--sri
Hi Sri and thank you for your help.
I'm not sure if my JMS Provider has such options, but I will check as these sounds as interesting options.
The retry system is interesting in your example, but this solution is still not good enough for my use cases:
Let's take my example again (In-CA, SA#1, SA#2, ...) and let's say that the exception is always thrown in SA#2 (due to a disconnected remote partner), and let's say that SA#1 generates a unique ID: as the retry logic is located in the JMS Provider, if I retry 5 times, I will go through SA#1 five times and thus generate five unique ID for the same message... If I retry 10000 times, I will then waste 10000 unique ID.
That's why I need a retry system located at SA#2 and not at the beginning of my flow. I really hope that INT-343 will be able to solve this case.
Thank you anyway for sharing your tips.
Pierre
Errr... I'm not sure how that would work.
I only want to retry when an exception occurs. If an exception occurs in SA#2, I won't reach anything that is placed after SA#2... And if no exception occurs in SA#2, I don't want a delay or any retry.
Moreover, the delayer only adds a delay, there is no retry logic within this component.
If you had an idea in mind, could you be more specific? I think I didn't get it properly...
Not sure where you want to implement the retry logic, but here is the algorithm.
In the service Activator, you want to implement the retry logic, inject MessagingTemplate object and a Channel reference (Say delayerChannel).
Once you catch the exception, Create a copy of the failed message and increment retryLimit header value. (This is a custom header you need to add for every message from start of the flow.). Using MessagingTemplate send this new message to delayerChannel. Once it is on the delayerChannel, it will go through delayer element, it will be delayed for xxx ms and then will be send back to your Service Activator for resending.
This is little over engineering for retry logic, but will work.
Key elements in this are, retryLimit custom header and creating a new copy of the failed message for every failed attempt and incrementing the retryLimit header value.
Hope this is clear.
--sri
Oh now I see. Well, indeed, this would work. With quite a big dependence to SI API, but it would probably work :)
Sounds a bit too intrusive to me, but thank you for the advice, sri!
This does seem to be a Spring JMS issue really, but Spring Integration adds a layer of smarts on top of that, so there might be some hooks you can use. To prevent the rollback you need to catch the exception and deal with it in the MessageListener, which in this case is the downstream message flow.
Spring Integration sensibly doesn't provide an exception handling strategy for synchronous flows - it's much easier to handle them in the calling thread. The problem here is that the calling thread belongs to the MessageListenerContainer, deep in Spring JMS.
You could start by looking at customizing the dispatcher for the downstream channel. By default it does catch exceptions and tries to deliver the message to other subscribers (see UnicastingDispatcher). In your case you want the fallback subscriber to get not only the message but the exception as well - you can do that by implementing an alternate form of the dispatcher in a few lines probably.
Or you could put a special service activator downstream of the message listener that just delegates to a gateway, pushing the message on downstream but taking control of the calling thread, and allowing you to catch exceptions and handle them.
Or you could add an AOP interceptor to the downstream Channel.send() and do the same thing. (This is likely to be the approach we take in Spring Integration 2.1 to add declarative retry and recovery to message flows generally.)
I am actually using special service activator downstream and also ResponseHandler for HttpRequestMessageHandler (INT-1587) to get the retry functionality and some exception handling.
Yes, you are right, this is JMS issue and we need handle of calling thread and or Exception handling mechanish at the begining of the flow. This way we can handle exceptions and account for the messages.
Thanks
sri