Announcement Announcement Module
Collapse
No announcement yet.
Inconsistent behavior when Exception is thrown from Transformer? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Inconsistent behavior when Exception is thrown from Transformer?

    Hi,

    I have tried searching the forums and looking in the reference manual for any information on this, but have found none.

    We're seeing some strange behaviour in the error-handling for one of our SI-flows (SI version 2.0.5.RELEASE). Brief explanation:

    1. The DataTransformer in the flow below is used to transform the message payload from DOMSource to a Java POJO.
    2. If the request contained invalid XML, the DataTransformer will fail and throw a custom exception (TransformerException)
    3. The exception is handled by the ExceptionHandler class in the transform-error chain. The ExceptionHandler iteratures through the causes of the MessagingException until it finds the custom exception type (or until it reaches the root cause).
    4. The message of the custom exception is transformed to a valid XML response and returned through the incoming gateway.

    Code:
    	<bean id="incoming-gateway"
    		class="org.springframework.integration.ws.SimpleWebServiceInboundGateway">
    		<property name="replyTimeout" value="25000" />
    		<property name="requestTimeout" value="25000" />
    		<property name="extractPayload" value="true" />
    		<property name="requestChannel"	ref="requestChannel" />
    		<property name="errorChannel" ref="transform-error" />
    	</bean>
    
    	<chain id="request-chain" input-channel="requestChannel">
    		<header-enricher>
    			<header name="channel" method="getChannelHeader" ref="channel-HeaderEnricher" />
    		</header-enricher>
    		<header-value-router header-name="channel">
    			<mapping value="transform" channel="transformer-channel" />
    		</header-value-router>
    	</chain> 
    
    
    	<chain input-channel="transformer-channel" >
    	
    		<transformer method="transform">
    			<beans:bean class="com.example.transformation.util.DataTransformer">
    			</beans:bean>
    		</transformer>
    	</chain>
    
    
    	<chain input-channel="transform-error">
    		<transformer method="transformExceptionMessageToResponse">
    			<beans:bean
    				class="com.example.exceptionhandling.ExceptionHandler">
    			</beans:bean>
    		</transformer>
    	</chain>
    The problem is that the above behaviour only works every other time. If we run this flow repeatedly using the same incorrect input data in every request, we get the desired behaviour the first time and every other time from then on. The stacktrace from the console for these desired exceptions is:

    org.springframework.integration.MessageHandlingExc eption: handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:104)
    at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:78)

    .......

    org.springframework.integration.dispatcher.Aggrega teMessageDeliveryException: All attempts to deliver Message to MessageHandlers failed. Multiple causes:
    org.springframework.integration.MessageHandlingExc eption: org.example.TransformerException: Failed to filter source.
    handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    See below for the stacktrace of the first cause.
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.handleExceptions(UnicastingDispatche r.java:160)
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :123)

    .......

    Caused by: org.springframework.integration.transformer.Messag eTransformationException: org.springframework.integration.MessageHandlingExc eption: org.example.TransformerException: Failed to filter source.
    at org.springframework.integration.transformer.Messag eTransformingHandler.handleRequestMessage(MessageT ransformingHandler.java:73)
    at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:98)

    .......

    Caused by: org.springframework.integration.MessageHandlingExc eption: org.example.TransformerException: Failed to filter source.
    However, the second time we run the request (and every other time from then on), the Exception thrown never contains our TransformerException among the nestled causes. Instead, the nestled causes of the MessagingException are all instances of org.springframework.integration.MessageHandlingExc eption. See stacktrace below:

    org.springframework.integration.MessageHandlingExc eption: handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:104)
    at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:78)

    ....

    org.springframework.integration.dispatcher.Aggrega teMessageDeliveryException: All attempts to deliver Message to MessageHandlers failed. Multiple causes:
    handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    org.springframework.integration.MessageHandlingExc eption: org.example.TransformerException: Failed to filter source.
    See below for the stacktrace of the first cause.
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.handleExceptions(UnicastingDispatche r.java:160)

    ....

    Caused by: org.springframework.integration.MessageHandlingExc eption: handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:104)

    .....

    at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :110)
    ... 137 more
    org.springframework.integration.dispatcher.Aggrega teMessageDeliveryException: All attempts to deliver Message to MessageHandlers failed. Multiple causes:
    handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    org.springframework.integration.MessageHandlingExc eption: org.example.TransformerException: Failed to filter source.
    See below for the stacktrace of the first cause.
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.handleExceptions(UnicastingDispatche r.java:160)
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :123)
    at org.springframework.integration.dispatcher.Unicast ingDispatcher.dispatch(UnicastingDispatcher.java:9 7)

    ....

    Caused by: org.springframework.integration.MessageHandlingExc eption: handler 'org.springframework.integration.transformer.Messa geTransformingHandler@1fe84e1' requires a reply, but no reply was received
    at org.springframework.integration.handler.AbstractRe plyProducingMessageHandler.handleMessageInternal(A bstractReplyProducingMessageHandler.java:104)
    at org.springframework.integration.handler.AbstractMe ssageHandler.handleMessage(AbstractMessageHandler. java:78)

    ....

    at org.springframework.integration.dispatcher.Unicast ingDispatcher.doDispatch(UnicastingDispatcher.java :110)
    ... 137 more
    Why does this happen? Does it have anything to do with the fact that Transformers must always return a reply?
    Last edited by anwi; Jun 21st, 2012, 04:11 AM.

  • #2
    When something happens "every other time", it usually points to having two subscribers on a channel (which by default uses round-robin dispatching).

    Is it possible you have another flow subscribed to errorChannel? We generally recommend using a specifically-named error channel instead of using the default errorChannel.

    Comment


    • #3
      Also, keep in mind that default errorChanne, is a PubSub channel so to Gary's point the round-robin only applies to a PointToPoint channel (e.g., DirectChannel) which means that also look if your errorChannel is explicitly defined as <channel> thus overriding its default implementation form PubSub to PointToPoint.

      Comment


      • #4
        Thank you for the quick response.

        I might have misunderstood something, but I don't think we're using the default errorChannel since we explicitly define an errorChannel on the Inbound Gateway.
        Code:
        	<bean id="incoming-gateway"
        		class="org.springframework.integration.ws.SimpleWebServiceInboundGateway">
        		<property name="replyTimeout" value="25000" />
        		<property name="requestTimeout" value="25000" />
        		<property name="extractPayload" value="true" />
        		<property name="requestChannel"	ref="requestChannel" />
        		<property name="errorChannel" ref="transform-error" />
        	</bean>
        I also couldn't find that we had two subscribers on the channel "transform-error" as the only definition is:
        Code:
        	<channel id="transform-error">
        		<queue capacity="500" />
        		<interceptors>
        			<wire-tap channel="errorlogger" />
        		</interceptors>
        	</channel>
        
        
        	<chain input-channel="transform-error">
        		<transformer method="transformExceptionMessageToResponse">
        			<beans:bean
        				class="com.example.exceptionhandling.ExceptionHandler">
        			</beans:bean>
        		</transformer>
        	</chain>
        Furthermore, when debugging the application we have found that the two cases follow the same flow, meaning that in both cases the exception is thrown in the transform-method of the DataTransformer and it is caught by the transformExceptionMessageToResponse of the ExceptionHandler. The history-header of the message is identical for both cases too. The only difference seems to be the exception thrown.

        If it's any help, full stack traces for both exception cases can be found at:
        http://dl.dropbox.com/u/28871422/stacktraces.zip

        Comment


        • #5
          Hello

          whould you explain, please, why your com.example.exceptionhandling.ExceptionHandler#tra nsformExceptionMessageToResponse may return null?
          It's not OK for Transformer: it should return not-null always. Otherwise you are are catching
          requires a reply, but no reply was received
          . The more: you have error-flow, where you try to restore "friendlier" behavior of your business process.

          Please, investigate your logic one more time.

          Take care,
          Artem Bilan

          Comment


          • #6
            Originally posted by Cleric View Post
            Hello

            whould you explain, please, why your com.example.exceptionhandling.ExceptionHandler#tra nsformExceptionMessageToResponse may return null?
            It's not OK for Transformer: it should return not-null always. Otherwise you are are catching
            . The more: you have error-flow, where you try to restore "friendlier" behavior of your business process.

            Please, investigate your logic one more time.

            Take care,
            Artem Bilan
            Hi Artem,

            Thanks for your reply. Our transformers never return null as a result, but they can however throw exceptions when they fail to transform the incoming message (which is the case here). Is throwing exceptions from a transformer not recommended?

            Regarding the second part of your response, I'm not quite sure I understand what you mean. Our error-flow doesn't try to restore a "friendlier" behavior of our business process, it simply converts the caught exception to an XML-response and returns this through the incoming-gateway

            Comment


            • #7
              Unfortunately for your logs can be seen that showed here config isn't enough to understand what's going on...
              You also have in your config <gateway> inside the <chain>, <router>.
              Can you debug your flow?
              And also: how about to switch to the latest Spring Integration version?
              but they can however throw exceptions when they fail to transform
              And what are you going to do with this Exception?
              Is throwing exceptions from a transformer not recommended?
              No, it's OK. But you should know what to do further with it.

              Try to escape of chains and set id for all components.
              It may help a bit for debriefing.

              Good luck!

              Comment


              • #8
                Originally posted by Gary Russell View Post
                When something happens "every other time", it usually points to having two subscribers on a channel (which by default uses round-robin dispatching).

                Is it possible you have another flow subscribed to errorChannel? We generally recommend using a specifically-named error channel instead of using the default errorChannel.
                It turns out you were right. We found that there was another chain defined which also had "transformer-channel" as input-channel, and this is what caused the error.

                Thanks for all the help!

                Comment


                • #9
                  If you are using SpringSource Tool Suite (or the eclipse plugins), a good diagnostic tool for these problems is to look a the "Integration Graph" tab for the config file. It currently only supports looking at single files, but it does give you a picture of how endpoints are connected with channels.

                  Comment

                  Working...
                  X