Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

Exception Strategy Most Common Use Cases

This page illustrates six ways to approach error handling within Mule applications.

The first two examples implement a transactional JMS queue and include a message transformer that appends a string to the original message. When an error occurs, Mule routes the message through the flow’s exception strategy into the JMS dead letter queue. These two examples differ principally in the “message state” they send to the dead letter queue.

About the Examples

  • The in-line numbers (that is, <!-- [1] -→) that conclude certain lines of code correspond to the numbered notes that appear immediately beneath the code.

  • Some of the examples use a throwException test component to simulate an error condition in a flow.

Route the Before-Error Message to the Dead Letter Queue

In this first case, the exception strategy recovers the message as it existed just before the error occurred. In other words, Mule has already transformed the message (that is, appended a string to the payload), but the message has not yet thrown an exception.


         
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<flow name="LastMessageStateRouting">
  <jms:inbound-endpoint queue="in">
     <jms:transaction action="ALWAYS_BEGIN" />
  </jms:inbound-endpoint>
  <append-string-transformer message=" with some text added"/> <!-- [1] -->
  <test:component throwException="true"/>
  <jms:outbound-endpoint queue="out">
    <jms:transaction action="ALWAYS_JOIN" />
  </jms:outbound-endpoint>
  <catch-exception-strategy>
    <jms:outbound-endpoint queue="dead.letter"> <!-- [2] -->
      <jms:transaction action="ALWAYS_JOIN" />
    </jms:outbound-endpoint>           
  </catch-exception-strategy>
</flow>
  1. Mule replaces the current payload with the version of the payload (that is, the transformed payload with the specified string appended) that emerged from the Append String Transformer just before the exception was thrown.

  2. Mule sends the transformed version of the message to the JMS dead letter queue. To accomplish this, Mule "joins" the transaction (that is, resumes the transaction with the version of the message that existed just before the exception was thrown) at the outbound connector embedded in the exception strategy. Mule commits the transaction after it routes the message through all the exception strategy message processors.

Route the Initial-State Message to the Dead Letter Queue

In this second case, rather than processing the message in its transformed state, the exception strategy must recover, then process the message in its initial, untransformed state. To ensure that Mule sends this initial-state message to the dead letter queue, Mule saves the message payload, in an originalMessage variable. Mule uses this variable to recover the initial-state message when an exception occurs.


         
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<flow name="OriginalMessageRouting">
  <jms:inbound-endpoint queue="in">
    <jms:transaction action="ALWAYS_BEGIN" />
  </jms:inbound-endpoint>
  <set-variable variableName="originalMessage" value="#[payload]"/> <!-- [1] -->
  <append-string-transformer message=" with some text added"/>
  <test:component/>
  <jms:outbound-endpoint queue="out">
     <jms:transaction action="ALWAYS_JOIN" />
  </jms:outbound-endpoint>
  <catch-exception-strategy>
    <set-payload value="#[flowVars['originalMessage']]"/> <!-- [2] -->
    <jms:outbound-endpoint queue="dead.letter">  <!-- [3] -->
       <jms:transaction action="ALWAYS_JOIN" />
    </jms:outbound-endpoint>
   </catch-exception-strategy>
</flow>
  1. To preserve the original message, Mule stores the original payload in a originalMessage variable.

  2. At this point, Mule replaces the current message payload with the one saved in the originalMessage variable.

  3. Mule sends the message, in its original state, to the dead letter queue.

Route the Message Based on Exception Type

Mule can execute different actions depending on the type of exception that a message throws. This is analogous to content-based routing. However, in this case, Mule determines a route for a message based on the type of exception it throws, rather than its payload.


         
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<flow name="RouteByExceptionType">
  <jms:inbound-endpoint queue="in">
     <jms:transaction action="ALWAYS_BEGIN" />
  </jms:inbound-endpoint>
  <test:component/>
  <jms:outbound-endpoint queue="out">
     <jms:transaction action="ALWAYS_JOIN" />
  </jms:outbound-endpoint>
  <choice-exception-strategy>
     <catch-exception-strategy when="exception.causedBy(com.company.BusinessException)"> <!-- [1] -->
     <jms:outbound-endpoint queue="dead.letter">
        <jms:transaction action="ALWAYS_JOIN" />
     </jms:outbound-endpoint>
     </catch-exception-strategy>
        <rollback-exception-strategy when="exception.causedBy(com.company.NonBusinessException)"> <!-- [2] -->
           <logger level="ERROR" message="Payload failing: #[payload]"/>
         </rollback-exception-strategy>
  </choice-exception-strategy>
</flow>
  1. When a message throws a com.company.BusinessException, the choice exception strategy routes the message to the catch-exception-strategy. The catch exception strategy sends the message to a dead letter queue, then consumes the source.

  2. When a message throws a com.company.NonBusinessException (that is, an unexpected failure), the choice exception strategy routes the message to the rollback-exception-strategy. The rollback exception strategy logs the error, then rolls back the JMS transaction to prepare to reprocess the message.

  3. If a message throws an exception that is neither BusinessException nor NonBusinessException, Mule’s implicitly-applied default exception strategy handles the error.

Returning an Error Message

Mule can catch an exception, then create an error message to return to the caller in a synchronous request-response scenario. The HTTP listener has built in support for this, through the error-response-builder child element.


         
      
1
2
3
4
5
6
7
8
9
10
11
12
<http:listener-config name="HttpListenerConfiguration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="CatchAndReturnError">
        <http:listener config-ref="HttpListenerConfiguration" path="getSomething" allowedMethods="GET" doc:name="Retrieve person">
           <http:error-response-builder statusCode="#[errorStatusCode]" reasonPhrase="#[errorReasonPhrase]"/>
       </http:listener
        <test:component throwException="true"/>
        <catch-exception-strategy>
                <set-variable variableName="errorStatusCode" value="404" doc:name="Set status code"/>
               <set-variable variableName="errorReasonPhrase" value="Not Found" doc:name="Set reason phrase"/>
        </catch-exception-strategy>
 
</flow>
  1. The catch exception strategy sets the variables errorStatusCode and errorReasonPhrase in the HTTP Listener’s child element.

  2. The HTTP Listener provides these two values as a response to the request made to it

Alternatively, you could achieve the same results by configuring your exception strategy like below:


         
      
1
2
3
4
<catch-exception-strategy>
   <set-payload value="The request cannot be processed, the error is #[exception.getSummaryMessage()]"/>
   <set-property propertyName="http.status" value="500"/>
</catch-exception-strategy>
  1. The catch exception strategy replaces the message payload with new content. Mule uses the Mule Expression Language MEL exception variable to include an error number in the message payload.

  2. The catch exception strategy sets the HTTP status code of the response to 500 to indicate a server error.

  3. Mule sends the new message payload to the caller.

Rollback the Transaction and Send a Notification

When an error occurs, Mule can rollback transactions, then send failure notifications to a system administrator. In this case, Mule rolls back the transaction, then uses an SMTP connector to send a failure notification email.


         
      
1
2
3
4
5
6
7
8
9
10
<flow name="RollbackTransactionAndSendEmail">
  <jms:inbound-endpoint queue="in">
     <jms:transaction action="ALWAYS_BEGIN"/>
  </jms:inbound-endpoint>
  <test:component throwException="true"/>
  <rollback-exception-strategy> <!-- [1] -->
    <set-payload value="#['Failed to process message: ' + payload]"/> <!-- [2] -->
    <smtp:outbound-endpoint user="me" password="mypassword" host="smtp.gmail.com" from="failures-app@mycompany.com" to="technical-operations@mycompany.com" subject="Message Failure"/>  <!-- [3] -->
  </rollback-exception-strategy>
</flow>
  1. Whenever a message throws an exception, Mule rolls back the transaction.

  2. Mule sets a new payload on the message which contains both:

    • The failure notification message Failed to process message:

    • The payload of the message

  3. Mule sends a failure notification email to technical-operations@mycompany.com.

Stop Processing When an Exception Occurs

Mule can prevent a flow from accepting any more messages after certain types of errors occur. For example, when an external service becomes unavailable (that is, goes offline), every message processing attempt fails until the unavailable resource is restored. In this case, Mule can shut down the flow to prevent it from attempting to process any more messages.


         
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<http:request-config name="request-config" host="localhost"
port="808"/>
<flow name="StopFlowBasedOnExceptionType">
   <vm:inbound-endpoint path="in" exchange-pattern="request-response"/>
   <http:request config-ref="request-config" path="/" method="GET" doc:name="HTTP Connector" responseTimeout="5"/>
   <choice-exception-strategy>
      <rollback-exception-strategy when="exception.causedBy(java.net.ConnectException)">  <!-- [1] -->
         <script:component>
           <script:script engine="groovy">
                        StopFlowBasedOnExceptionType.stop();
            </script:script>           </script:component>
       </rollback-exception-strategy>        <rollback-exception-strategy> <!-- [2] -->            <logger/>
       </rollback-exception-strategy> </choice-exception-strategy>
</flow>
  1. When the exception type is ConnectionException, the choice exception strategy routes the message to the first rollback exception strategy. The rollback exception strategy runs a script that stops the flow from processing any more messages.

  2. For all other exception types, the choice exception strategy routes the message to the second rollback exception strategy, which logs the error.