Results 1 to 9 of 9

Thread: Inconsistent behavior when Exception is thrown from Transformer?

  1. #1
    Join Date
    Jun 2012
    Posts
    9

    Question 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 at 04:11 AM.

  2. #2
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,037

    Default

    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.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #3
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    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.

  4. #4
    Join Date
    Jun 2012
    Posts
    9

    Default

    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

  5. #5
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    646

    Default

    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

  6. #6
    Join Date
    Jun 2012
    Posts
    9

    Default

    Quote 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

  7. #7
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    646

    Default

    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!

  8. #8
    Join Date
    Jun 2012
    Posts
    9

    Default

    Quote 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!

  9. #9
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,037

    Default

    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.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •