Announcement Announcement Module
Collapse
No announcement yet.
Handling Exceptions in Interceptors Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Handling Exceptions in Interceptors

    I have the following configuration:

    Code:
     <!-- Base Gateway Message Channel -->
      <integration:channel id="gatewayMessageChannel">
        <integration:interceptors>
          <ref bean="gatewayTransformingInterceptor"/>
          <ref bean="jsonInterceptor"/>
        </integration:interceptors>
      </integration:channel>
    The first interceptor is basically a transformer. It takes an external message format, e.g.:

    Code:
    <message>
      <header>
        ..header fields
      </header>
      <payload>
       ...payload data
      </payload>
    </message>
    and extracts the headers and payload and converts the incoming message to a SI Message format.

    The second interceptor parses the payload as a JSON message and extracts a 'type' attribute in the message payload that is used in routing.

    With both of these interceptors, if the message format is incorrect (bad xml, missing fields, bad json, etc) then the message is not recoverable and there is no point in having the jms provider redeliver it. I just need to log the event and drop it on the floor.

    Initially I had the interceptors return NULL if they could not process the message. This, however, was causing rollback. The message channel docs say:

    http://static.springsource.org/sprin...n.core.Message)

    Send a Message to this channel. May throw a RuntimeException for non-recoverable errors.
    So I changed the code to throw a RuntimeException instead of returning null in my interceptors. However, that exception is still bubbling all the way up to the message listener container and the message is still being rolled back.

    The rest of my message processing takes place in a chain:

    Code:
    <integration:chain input-channel="gatewayMessageChannel">
         <!-- Throw away duplicate messages -->
         <integration:filter ref="duplicateMessageSelector"/>
         <!-- Route messages to appropriate channels for handling -->
         <integration:router ref="jsonMessageTypeRouter" default-output-channel="unroutableMessageChannel"/>
       </integration:chain>
    Here I check for incoming duplicate messages (in the db) and then route them to the appropriate channel for processing.

    Is there a better way to handle these error conditions? Can I just make them Transformers that return NULL in the case that they can't process the message (will this trigger a redelivery as well)?

    I certainly want exceptions (such as temporary db access) that are recoverable to trigger message delivery but I don't want to waste my time when repeated attempts to reprocess the message will never succeed.

    Thanks!

  • #2
    Have you tried moving those Transformers into the chain rather than in the channel?

    If the Transformers are themselves configured as "handlers/endpoints" rather than in channel interceptors, then they can return null, and it should be considered "done" (and hence ignored) as far as the Message flow is concerned.

    Comment


    • #3
      Originally posted by Mark Fisher View Post
      Have you tried moving those Transformers into the chain rather than in the channel?

      If the Transformers are themselves configured as "handlers/endpoints" rather than in channel interceptors, then they can return null, and it should be considered "done" (and hence ignored) as far as the Message flow is concerned.
      I haven't tried that yet. I wanted confirmation that returning null in the transform method would in fact just terminate the chain (like the filter returning false) and not cause further problems.

      I'll refactor things and see how it works...

      Thanks Mark.

      Comment


      • #4
        Please do try that. The difference is that a ChannelInterceptor returning null in the preSend() method produces a MessageDeliveryException in the AbstractMessagingGateway (where it delegates to MessageChannelTemplate and considers a 'false' return from the send method to be a failure).

        Comment


        • #5
          Originally posted by Mark Fisher View Post
          Please do try that. The difference is that a ChannelInterceptor returning null in the preSend() method produces a MessageDeliveryException in the AbstractMessagingGateway (where it delegates to MessageChannelTemplate and considers a 'false' return from the send method to be a failure).
          Works like a champ. Thanks Mark!

          Code:
          <!-- Gateway message handler chain -->
            <integration:chain input-channel="gatewayMessageChannel">
               <!-- Reformat message -->
               <integration:transformer ref="gatewayMessageTransformer"/>
               <!-- Extract JSON type header -->
               <integration:transformer ref="jsonMessageTypeExtractingTransformer"/>
               <!-- Throw away duplicate messages -->
               <integration:filter ref="duplicateMessageSelector"/>
               <!-- Route messages to appropriate channels for handling -->
               <integration:router ref="jsonMessageTypeRouter" default-output-channel="unroutableMessageChannel"/>
             </integration:chain>

          Comment

          Working...
          X