Results 1 to 9 of 9

Thread: Error-channel and nested gateway calls

  1. #1
    Join Date
    Jun 2012
    Posts
    9

    Question Error-channel and nested gateway calls

    I've searched the forums and the documentation but could not find any answer to my question there. We're using Spring Integration 2.0.5.RELEASE.

    Anywhere an exception occurs in our application, we want the exception to go to the "transform-error-to-response" channel where it is transformed into a proper response message and returned to the user.

    To make this possible we set the error-channel on the very first gateway call used for incoming requests, and then never set an error-channel further down the flow like below:

    Code:
    	<chain input-channel="incoming-requestChannel">
    		<gateway request-channel="service1-channel" error-channel="transform-error-to-response" />
    	</chain>
    
    
    	<chain id="Service1-chain" input-channel="service1-channel" >
    		
    		<gateway request-channel="performValidation-Channel" />
    
    		<header-enricher>
    			<header name="request" expression="payload" />
    		</header-enricher>
    						
    		<recipient-list-router apply-sequence="true" >
    			<recipient channel="call-foo-service" />
    			<recipient channel="call-bar-service" />
    		</recipient-list-router>
    	</chain>
    
    	<chain id="performValidation-chain" input-channel="performValidation-Channel" > 
    		<service-activator ref="inputValidator" ></service-activator>
    	</chain>
    
    	<chain input-channel="call-foo-service" output-channel="handle-foo-result">
    		<gateway request-channel="foo-channel">
    	</chain>
    However, when an exception occurs in the flow of "foo-channel", the exception does not go to the "transform-error-to-response" channel defined as error channel in the first error call. Instead the flow goes to some other, unknown error channel (not the default errorChannel either).

    To get the error to reach the "transform-error-to-response" channel as intended, we have to add an errorChannel to the gateway call to "foo-channel" which has a call to a service activator which simply re-throws the exception:

    Code:
    	<chain input-channel="call-foo-service" output-channel="handle-foo-result">
    		<gateway request-channel="foo-channel" error-channel="propagate-exception">
    	</chain>
    
    	<chain input-channel="propagate-exception">
    		<service-activator method="propagateErrorMessage">
    			<beans:bean class="com.example.errorhandling.ErrorPropagator"/>
    		</service-activator>
    	</chain>
    Code:
    public class ErrorPropagator {
    
    	public void propagateErrorMessage(Message<MessagingException> exceptionMsg) throws MessagingException{	
    		MessagingException msgExp = exceptionMsg.getPayload();
    		throw msgExp;
    	}	
    }
    So my question is: Why is this extra error-channel which re-throws the error needed? My understanding was that since the error-channel is initially set to "transform-error-to-response" and then never overwritten, this would be the channel used when any exception occurs downstream.

  2. #2
    Join Date
    Jun 2012
    Posts
    9

    Default

    I have done some experimenting with moving and removing components and found that this seems to be related to the usage of chains.

    I have been able to reduce the config for when this error occurs to:

    Code:
    	<chain input-channel="incoming-requestChannel">
    		<gateway request-channel="service1-channel" error-channel="transform-error-to-response" />
    	</chain>
    
    	<chain id="Service1-chain" input-channel="service1-channel" >
    		<gateway request-channel="call-foo-service" />
    	</chain>
    
    	<chain input-channel="call-foo-service" />
    		<gateway request-channel="foo-channel">
    	</chain>
    If an exception occurs after the call to foo-channel here, the error is not thrown to "transform-error-to-response".
    However, if we bypass the final chain and call "foo-channel" straight from the "Service1-chain", the error goes to "transform-error-to-response" as expected:
    Code:
    	<chain input-channel="incoming-requestChannel">
    		<gateway request-channel="service1-channel" error-channel="transform-error-to-response" />
    	</chain>
    
    	<chain id="Service1-chain" input-channel="service1-channel" >
    		<gateway request-channel="foo-channel" />
    	</chain>

    I still don't understand why this happens though.

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

    Default

    Hello

    I've written some test-case based on your issue:
    Config:
    HTML Code:
    <channel id="input"/>
    
    <channel id="chain1Channel"/>
    
    <channel id="chain2Channel"/>
    
    <channel id="serviceChannel"/>
    
    <channel id="errorChannel"/>
    
    <chain input-channel="input">
    	<gateway request-channel="chain1Channel" error-channel="errorChannel"/>
    </chain>
    
    <chain input-channel="chain1Channel">
    	<gateway request-channel="chain2Channel"/>
    </chain>
    
    <chain input-channel="chain2Channel">
    	<gateway request-channel="serviceChannel"/>
    </chain>
    
    <payload-type-router input-channel="serviceChannel" resolution-required="true">
    	<mapping type="java.lang.String" channel="fooChannel"/>
    </payload-type-router>
    
    <outbound-channel-adapter channel="errorChannel">
    	<beans:bean class="org.springframework.integration.handler.ChainExceptionPropagationTests$TestErrorHandler"/>
    </outbound-channel-adapter>
    Test Class
    Code:
    @ContextConfiguration
    @RunWith(SpringJUnit4ClassRunner.class)
    public class ChainExceptionPropagationTests {
    
    	@Autowired
    	MessageChannel input;
    
    	@Test
    	public void testChainExceptionPropagation() {
    		try {
    			this.input.send(MessageBuilder.withPayload(1).build());
    		}
    		catch (Exception e) {
    			assertEquals("intentional", e.getCause().getMessage());
    		}
    	}
    
    	private static class TestErrorHandler implements MessageHandler {
    
    		@Override
    		public void handleMessage(Message<?> message) throws MessagingException {
    			throw new RuntimeException("intentional");
    		}
    	}
    
    }
    But if I made some of the 'chain1Channel' or 'chain2Channel' as queue my test hangs.
    So, maybe do you have similar channel config?
    By default asynchronous message-flows send their Exceptions into default "errorChannel": http://static.springsource.org/sprin...e-errorhandler

    So, WDYT?

    Take care,
    Artem

  4. #4
    Join Date
    Jun 2012
    Posts
    9

    Default

    Quote Originally Posted by Cleric View Post
    But if I made some of the 'chain1Channel' or 'chain2Channel' as queue my test hangs.
    So, maybe do you have similar channel config?
    By default asynchronous message-flows send their Exceptions into default "errorChannel": http://static.springsource.org/sprin...e-errorhandler

    So, WDYT?

    Take care,
    Artem
    Hi Artem,

    Thank you for your reply.

    Yes, we do have a similar config. Our "incoming-requestChannel" has a ThreadPoolTaskExecutor attached to it:

    Code:
    <beans:bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <beans:property name="corePoolSize" value="50"/> 
    <beans:property name="maxPoolSize" value="200" />
    <beans:property name="queueCapacity" value="1" />
    </beans:bean>
    
    <channel id="incoming-requestChannel">
    <dispatcher task-executor="taskExecutor" />
    </channel>
    You say that the default behavior for asynch message flows is to send their exceptions to the "errorChannel", but this doesn't seem to be the case here. I've tried attaching custom error-handling to the "errorChannel", but the exception did not reach that flow.

    I also thought that once we explicitly stated an error-channel property, as we do in the "incoming-requestChannel" chain, the default behavior will not be applied anymore.
    Last edited by anwi; Oct 1st, 2012 at 05:14 AM.

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

    Default

    Hi!

    H-m-m...
    Can you show channels' config for this one:
    <chain input-channel="incoming-requestChannel">
    <gateway request-channel="service1-channel" error-channel="transform-error-to-response" />
    </chain>

    <chain id="Service1-chain" input-channel="service1-channel" >
    <gateway request-channel="call-foo-service" />
    </chain>

    <chain input-channel="call-foo-service" />
    <gateway request-channel="foo-channel">
    </chain>
    I need to know: who are they?

  6. #6
    Join Date
    Jun 2012
    Posts
    9

    Default

    Hi,

    I made a mistake in my previous post which I have now edited. The task-executor is attached to the "incoming-requestChannel" and nothing else.

    I'm not sure what more info I can give you. incoming-requestChannel is the only channel explicitly defined. All other channels are only mentioned in the chains above and have no separate definition.

    As for "foo-channel", it is a complex flow but I still get this error if I just change it to point to a Service Activator with a method that just throws an exception.

    If you need any more information, please let me know.

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

    Default

    Does your config is approximated to this one:
    HTML Code:
    <task:executor id="executor" pool-size="50-200" queue-capacity="1"/>
    
    	<channel id="input">
    		<dispatcher task-executor="executor"/>
    	</channel>
    
    	<channel id="errorChannel1"/>
    
    	<chain input-channel="input">
    		<gateway request-channel="chain1Channel" error-channel="errorChannel1"/>
    	</chain>
    
    	<chain input-channel="chain1Channel">
    		<gateway request-channel="chain2Channel"/>
    	</chain>
    
    	<chain input-channel="chain2Channel">
    		<gateway request-channel="serviceChannel"/>
    	</chain>
    
    	<payload-type-router input-channel="serviceChannel" resolution-required="true">
    		<mapping type="java.lang.String" channel="fooChannel"/>
    	</payload-type-router>
    
    	<outbound-channel-adapter channel="errorChannel1">
    		<beans:bean class="org.springframework.integration.handler.ChainExceptionPropagationTests$TestErrorHandler"/>
    	</outbound-channel-adapter>
    
    	<logging-channel-adapter channel="errorChannel" level="FATAL"/>
    For me it's working excelent:
    1. <payload-type-router> throws Exception about "channel resolution"
    2. My ChainExceptionPropagationTests$TestErrorHandler rethrows a intentional Exception
    3. <ogging-channel-adapter> logs a FATAL about the last one

    Now I really don't understand what's going on...
    Can you switch to the latest Spring Integration version?

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

    Default

    I have not had a chance to read the whole post in details, but I see you are asking about nested gateways with respect of errors going to the appropriate error-channel.
    I spoke about this use case in the last year's SpringOne and I'd suggest to look at the following sample https://github.com/olegz/s12gx.2011/...n/segmentation

    Let us know

  9. #9
    Join Date
    Jun 2012
    Posts
    9

    Default

    Hello,

    I am no longer part of the project, so I'm afraid I can't test with a new version of Spring Integration or provide further testing.

    Our config was pretty much identical to the one provided by Cleric, but we did not get the same behavior. Comparing with Cleric's config our ChainExceptionPropagationTests$TestErrorHandler was never invoked because the error for some reason did not route to "errorChannel1".

    Perhaps we had configured something incorrectly or perhaps there was an issue with our version of Spring Integration. Either way I am content with knowing that the behavior we saw was not intended.

    Thank you for your help!
    Regards
    Andreas

Posting Permissions

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