Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Handling mail outbound exceptions

  1. #1
    Join Date
    Apr 2012
    Posts
    24

    Default Handling mail outbound exceptions

    Hello,

    I have a simple flow that sends a mail via an outbound adapter and logs the message:

    Code:
    	<int:channel id="channel.send" />
    	<mail:outbound-channel-adapter order="1" channel="channel.send" mail-sender="mailSender"/>	
    	<bean id="logger" class="com.blah.MessageLogger" />
    	<int:service-activator order="2" input-channel="channel.send"
    		ref="logger" />
    This works as expected.

    I would like to implement exception handling, so if the email can not be sent (ie mail server down), I can modify the message and log it.

    I can't find the documentation on exception handling in this instance. Can anyone help?


    John

  2. #2
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    740

    Default

    Hello

    The <mail:outbound-channel-adapter> is a tipical Spring Integration component, so it has the same functionality around Exceptions as others. This paragraph should help you: http://static.springsource.org/sprin...e-errorhandler

    However I see a problem in your config:
    1. You have a DirectChannel and two his subscribers.
    2. By default this channel use on background UnicastingDispatcher with RoundRobinLoadBalancingStrategy
    3. So, the first Message will be send to <mail:outbound-channel-adapter>, but the second to <int:service-activator> and so on, through the times. Confused?

    To allow to work ordering you should make this:
    HTML Code:
    <channel id="channel.send">
    	<dispatcher load-balancer="none"/>
    </channel>
    Now your Message will always be sended to <mail:outbound-channel-adapter>, and it will be sended to <int:service-activator> only when Exception causes on email sending process.

    Is it what are you looking for?

    Cheers,
    Artem

  3. #3
    Join Date
    Apr 2012
    Posts
    24

    Default

    Hello

    That's helpful as I didn't realise I needed <dispatcher load-balancer="none"/> to make order work. Oddly, it was sending the message to both the mail outbound adapter and the logger. I stepped through the SI code to ensure it did.

    But, what I'm looking for is information on how to deal with exceptions from the mail adapter. ie I want to catch it and set a value on the message header.

    I tried adding a service activator to the default errorChannel but it's not called by the (deliberately failing) mail outbound adapter:

    Code:
    	<bean id="errorHandler" class="com.blah.ErrorHandler" />
    	<int:service-activator input-channel="errorChannel" ref="errorHandler" />
    John
    Last edited by jbakerc; Aug 15th, 2012 at 05:27 AM.

  4. #4
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    740

    Default

    I want to catch it
    So, read the Manual, where I've pointed.
    And also for logging I recommend to use <wire-tap>

  5. #5
    Join Date
    Apr 2012
    Posts
    24

    Default

    Yes, I read the manual, added a service activator listening to errorChannel, stepped through the code and when the exception is thrown by the mail outbound adapter, the service activator isn't called.

  6. #6
    Join Date
    Apr 2012
    Posts
    24

    Default

    Update, the following is required to make the UnicastDispatcher stop and throw an exception when iterating through the list of message handlers:

    Code:
    		<int:dispatcher load-balancer="none" failover="false" />
    However, whilst that spits out the exception to the stdout log, it doesn't seem to call my error handler.

    If it helps, I'm reading the original message from JMS.

  7. #7
    Join Date
    Apr 2012
    Posts
    24

    Default

    Case closed. The JMS adapter needs to be explicitly told about the error channel, which I feel is not a great solution given it should use the default errorChannel automatically as per the documentation.

    Code:
    	<int-jms:message-driven-channel-adapter ... error-channel="errorChannel" />
    Cleric, as a matter of interest, how would I re-write the mail/log example above without using order? ie can the mail adapter push the message to another channel when it completes? I couldn't see an out channel attribute.

  8. #8
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    740

    Default

    how would I re-write the mail/log example above without using order?
    What does your com.blah.MessageLogger do with the Message?
    ie can the mail adapter push the message to another channel when it completes?
    No, it can't. It is a one-way component. By the way: if send an email message manualy via javax.mail.Session, do you have any return ?

    What do you want to get with "it completes" case?
    Maybe this will be enough:
    HTML Code:
    <int:publish-subscribe-channel id="channel.send" />
    <mail:outbound-channel-adapter order="1" channel="channel.send" mail-sender="mailSender"/>	
    <int:service-activator ref="afterSendEmailService"/>
    Here "channel.send" has several subscribers and the channel sends inbound Message to them all.
    But it will be done one by one at the same thread. So, if your <mail:outbound-channel-adapter> throws Exception the Message won't be sended to the <int:service-activator>

    Is it appropriate?

  9. #9
    Join Date
    Apr 2012
    Posts
    24

    Default

    HTML Code:
    <int:publish-subscribe-channel id="channel.send" />
    <mail:outbound-channel-adapter order="1" channel="channel.send" mail-sender="mailSender"/>	
    <int:service-activator ref="afterSendEmailService"/>
    Yes, this is what I was looking for, and what I was trying to do with the order in the previous snippet.

  10. #10
    Join Date
    Apr 2012
    Posts
    24

    Default

    It's a pity that a new message is passed to the error handler, and not the existing message with a new payload. From MessagingGatewaySupport:

    Code:
    		catch (Exception e) {
    			if (this.errorChannel != null) {
    				this.messagingTemplate.send(this.errorChannel, new ErrorMessage(e));
    			}
    			else {
    				this.rethrow(e, "failed to send message");
    			}
    I wanted to read values from the headers in order to help deal with the error.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •