Search code examples
muleesbmule-studiomule-flow

Mule flow execution unexpectedly splits on error in SMTP sendout


I would like to catch errors from SMTP endpoint (for example in case it's misconfigured or the server is down) and when this happens, prevent messages from proceeding the normal path and rather go into an exception flow. An exception handler works and messages are routed into an exception flow. What is unexpected is that the message is duplicated and also proceeds with the "normal" flow as well. I would expect it to go only in one direction: if an email was sent successfully go into a normal endpoint, if sendout failed go into an exception endpoint.

In the provided example below, smtp is failing with UnknownHostException and the message goes into failureEndpoint but the message for some reason also ends up in the outboundEndpoint:

<mule><!-- namespaces omitted for readability -->
    <flow name="sample-flowFlow1" doc:name="sample-flowFlow1">
        <inbound-endpoint ref="inboundEndpoint" doc:name="AMQP Consumer"/>
        <smtp:outbound-endpoint host="foobaz" to="[email protected]" from="[email protected]" subject="test" responseTimeout="10000" doc:name="SMTP"/>
        <outbound-endpoint ref="outboundEndpoint" doc:name="AMQP Publisher"/>
        <exception-strategy ref="FailureNotification" doc:name="Publish failure notification" />
    </flow>

    <catch-exception-strategy name="FailureNotification">
        <flow-ref name="FailureNotificationFlow" doc:name="Flow Reference" />
    </catch-exception-strategy>
    <sub-flow name="FailureNotificationFlow" doc:name="FailureNotificationFlow">
        <outbound-endpoint ref="failureEndpoint" doc:name="Failure Endpoint"/>
    </sub-flow>
</mule>

When a message is published on inboundEndpoint and SMTP connector is misconfigured the way it is done in the provided example, I would like to see the message exclusively in the failureEndpoint, not in both outboundEndpoint and failureEndpoint. How do I accomplish this?

Mule version: 3.4.0


Solution

  • In this flow you are using multiple outbounds. The flow doesn't wait for the response of the smtp and still continues with the next out-bound.
    A condition can be added to check whether the smtp was successful before proceeding with the out-bound.

    The modified flow looks like this. Try this.

    <flow name="sample-flowFlow1" doc:name="sample-flowFlow1">
        <inbound-endpoint ref="inboundEndpoint" doc:name="AMQP Consumer"/>
        <flow-ref name="mailingFlow" ></flow-ref>       
        <choice>
            <when expression="#[flowVars['mailingSuccess'] == 'failure']">
                <logger level="INFO" message="Mailing failed"></logger>
            </when>
            <otherwise>
                <outbound-endpoint ref="outboundEndpoint" doc:name="AMQP Publisher"/>       
            </otherwise>
        </choice>                   
    </flow>
    
    <flow name="mailingFlow" processingStrategy="synchronous" >
        <smtp:outbound-endpoint host="foobaz" to="[email protected]" from="[email protected]" subject="test" responseTimeout="10000" doc:name="SMTP"/>
        <catch-exception-strategy name="FailureNotification">
            <set-variable variableName="mailingSuccess" value="failure" ></set-variable>
            <flow-ref name="FailureNotificationFlow" doc:name="Flow Reference" />        
        </catch-exception-strategy>
    </flow>
    
    <sub-flow name="FailureNotificationFlow" doc:name="FailureNotificationFlow">
        <outbound-endpoint ref="failureEndpoint" doc:name="Failure Endpoint"/>
    </sub-flow>
    

    Hope this helps