Announcement Announcement Module
Collapse
No announcement yet.
Exception in a Transformer is not propagated to the error channel Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Exception in a Transformer is not propagated to the error channel

    Am I wrong or an exception thrown in a Transformer (including header-enricher) is not propagated to the errorChannel?

    I am using an errorChannel in an asynchronous flow. I am using header-enricher to compute the value of a header. The method computing the value throws an exception, but the message is not relayed to the error channel.

    I replaced the header-enricher with my own Transformer working on the incoming Message object. The result was the same. Only when I used a Service Activator the exception was reaching the error channel.

    BTW, is there any difference between a Transformer and a Service Activator? They look pretty much the same to me regarding their role - they handle input messages and return output messages.

  • #2
    Could you please post your configuration?

    As far as ServiceActivator vs Transformer you can look at the Transformer as specialized ServiceActivator which has a job of transforming the content of the Message while generic Service Activator is for invoking a custom code triggered by the arrival of the Message.
    Having said all that, you can use ServiceActivator and implement transformation logic. I would not recommend that but just to make a point.

    Anyway, post your configuration since what you are describing should work.

    Comment


    • #3
      Hi Oleg,

      You say that the service activator is used to invoke custom code - it's true, but it is still transforming the the incoming message, because it has to return the payload of the following message. Also, as long as I implement the transformer it is still custom code triggered by the arrival of a message. You may say that the transformer kind of needs access to headers and payload, if it is to transform the message, but this is not mandatory. And also the service activator can have access to the headers, so I don't see a difference here. The only difference I could see so far is this one with the exception, and the fact that there are some out-of-box transformer implementations provided by Spring.

      Coming back to the configuration: this is a test/exploring configuration and I have left out the beans. Basically a boolean message goes to "startChannel", then it is split into a list of 10 integer (from 1 to 9). The action happens in channel2, where for every third message an exception is thrown in "computeHeader", just for test, you know. Those messages simply disappear when using transformers, but reach the error channel when using the service activator.

      I only used one of header-enricher, MyTransformer, or MethodHeaderEnricher (as service activator) at a time, and only the last one works as expected.


      HTML Code:
        <int:channel id="startChannel">
          <int:dispatcher task-executor="exec"/>
        </int:channel>
      
        <int:channel id="channel2">
          <int:dispatcher task-executor="exec"/>
        </int:channel>
      
        <int:chain input-channel="errCh" output-channel="nullChannel">
          <int:service-activator ref="errorLogger"/>
          <int:service-activator expression="payload.failedMessage"/>
           <int:service-activator ref="logger"/> 
        </int:chain>
      
        <int:chain input-channel="startChannel" output-channel="channel2">
          <int:header-enricher default-overwrite="true">
            <int:error-channel ref="errCh"/>
          </int:header-enricher>
          <int:splitter ref="splitter" method="split1"/>
        </int:chain>
      
        <int:chain input-channel="channel2" output-channel="aggregator1Channel">
      <!--    <int:transformer>-->
      <!--      <bean class="test.MyTransformer"/>-->
      <!--    </int:transformer>-->
          <int:service-activator>
            <bean class="test.MethodHeaderEnricher">
              <property name="bean" ref="intProcessor"/>
              <property name="method" value="computeHeader"/>
              <property name="header" value="dummy"/>
            </bean>
          </int:service-activator>
          <!-- <int:header-enricher default-overwrite="true"> -->
          <!-- <int:header name="dummy" ref="intProcessor" method="computeHeader"/> -->
          <!-- </int:header-enricher> -->
          <int:service-activator ref="logger"/>
          <int:service-activator ref="intProcessor" method="process1"/>
        </int:chain>
      
        <int:inbound-channel-adapter channel="startChannel"
          expression="true">
          <int:poller fixed-delay="10000"/>
        </int:inbound-channel-adapter>

      Comment


      • #4
        As I said, the difference between ServiceActivator and Transformer is semantical. One could be used in place of another, but semantically Transformer is used for different purposes then ServiceActivator.
        To get a better idea please read this: http://www.eaipatterns.com/ which is pretty much our requirement spec.
        http://www.eaipatterns.com/MessagingAdapter.html as well as Message Transformation patterns. IN fact HeaderEnricher is a transformer provided by the framework.

        As far as your configuration, it is had to determine what exactly you are trying to do here since there are a lot of things missing so I went based on your use cases and attached the test case and config that addresses what you want to do.
        Hope that helps

        Comment


        • #5
          Hi Oleg,

          I got to the bottom of this error. The culprit was my custom logging method, which looked like this:



          HTML Code:
          public Message<?> process(Message<MessageHandlingException> message) {
          
              if (logger.isEnabledFor(Level.ERROR)) {
          
                MessageHandlingException exc = message.getPayload();
          
                logger.error("", exc);
                logger.error("Failed message: " + exc.getFailedMessage());
              }
          
              return message;
            }

          The problem is, in that particular case the exception is of type MessageTransformationException, for which I had no matching logging method.

          Thanks Oleg, you have been a real help, I appreciate it. Keep up the good work!

          Comment

          Working...
          X