Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: A "gateway" in the middle of a "chain" resets the error channel header

  1. #1

    Exclamation A "gateway" in the middle of a "chain" resets the error channel header

    I have a chain processing a message coming from a channel ("startChannel"). The message has a custom error channel header. Somewhere in the middle of the chain I pass the message to a another channel ("channel2"), using an embedded "gateway" construct. I notice that the error channel header of the message is getting lost while traveling on "channel2", and then is set back to its initial value when the message returns to "startChannel". Is this a bug or does it happen intentionally? To me it looks suspicious, and indeed, if an error happens while the message is processed in "channel2", then the message is simply lost, without reaching my "errCh1" channel.

    The configuration looks like this:

    Code:
      <int:message-history/>
    
      <int:channel id="errCh1"/>
    
      <int:chain input-channel="errCh1">
        <int:service-activator ref="logger"/>
      </int:chain>
    
      <int:chain input-channel="startChannel">
        <int:header-enricher default-overwrite="true">
          <int:error-channel ref="errCh1"/>
        </int:header-enricher>
        <int:service-activator ref="logger"/>
        <int:gateway request-channel="channel2"/>
        <int:service-activator expression="'after'"/>
        <int:service-activator ref="logger"/>
      </int:chain>
    
      <int:chain input-channel="channel2">
        <int:service-activator expression="25"/>
        <int:service-activator ref="logger"/>
        <int:service-activator ref="processor"/>
      </int:chain>
    
      <int:inbound-channel-adapter channel="startChannel"
        expression="'startChannel payload'">
        <int:poller fixed-rate="10000"/>
        <int:header name="replyChannel" value="nullChannel"/>
      </int:inbound-channel-adapter>
    
      <bean id="processor" class="test.Processor"/>
    The log result looks like this:

    Code:
    [DEBUG] [2011/27/01 12:22:47,237] [task-scheduler-1] [MessageLogger.log] [Payload=startChannel payload][Headers={errorChannel=errCh1, replyC
    hannel=nullChannel, timestamp=1296148967209, history=startChannel, id=ac778d4f-396c-4790-916d-c07a5e3c75ce}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/27/01 12:22:47,257] [task-scheduler-1] [MessageLogger.log] [Payload=25][Headers={errorChannel=org.springframework.integration.
    core.MessagingTemplate$TemporaryReplyChannel@853e51, replyChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChann
    el@853e51, timestamp=1296148967256, history=startChannel,channel2, id=e24a2ef0-6e21-4960-be3b-10899e92f137}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/27/01 12:22:47,261] [task-scheduler-1] [MessageLogger.log] [Payload=after][Headers={errorChannel=errCh1, replyChannel=nullChan
    nel, timestamp=1296148967260, history=startChannel,channel2, id=6ecc72e4-c2c3-4f22-8814-0f7aa51a2228}] at (MessageLogger.java:25)

  2. #2
    Join Date
    Nov 2008
    Location
    Swansea, Wales
    Posts
    202

    Default

    Have you tried setting the error-channel attribute on the Gateway to errCh1?

    Code:
    <int:gateway request-channel="channel2" error-channel="errCh1"/>
    It looks from the code that if you don't supply an error channel then no error channel gets set on the MethodInvocationGateway and therefore the GatewayProxyFactoryBean will just re-throw the exception. GatewayProxyFactoryBean doesnt set the error channel at runtime based on the message header just at startup based on the config. I would imagine that your exception is not getting lost, it is just going to the default error channel.

  3. #3

    Default

    The attribute "error-channel" is not allowed for a gateway element embedded into a chain. I get an xml exception when I try to create the Spring context.

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

    Default

    Yes it is true for 2.0.1, but it was addressed for 2.0.2 https://jira.springsource.org/browse/INT-1745 and is currently available with the snapshot builds.
    Can you please test it? If you are using maven simply point your SI to the version 2.0.2.BUILD-SNAPSHOT
    Last edited by oleg.zhurakousky; Jan 28th, 2011 at 10:22 AM.

  5. #5

    Default

    I just tested it with 2.0.2.BUILD-SNAPSHOT. I can set the attribute "error-channel" on the gateway now, but it has no effect.

    Code:
    [DEBUG] [2011/28/01 11:26:01,163] [task-scheduler-1] [MessageLogger.log] [Payload=startChannel payload][Headers={errorChannel=errCh1, replyC
    hannel=nullChannel, timestamp=1296231961146, history=startChannel, id=2d40383a-72b2-42e9-862d-ee431d049363}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/28/01 11:26:01,182] [task-scheduler-1] [MessageLogger.log] [Payload=25][Headers={errorChannel=org.springframework.integration.
    core.MessagingTemplate$TemporaryReplyChannel@b6a350, replyChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChann
    el@b6a350, timestamp=1296231961181, history=startChannel,channel2, id=646f7632-f0cd-4e4a-b721-39339db4ddfc}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/28/01 11:26:01,187] [task-scheduler-1] [MessageLogger.log] [Payload=after][Headers={errorChannel=errCh1, replyChannel=nullChan
    nel, timestamp=1296231961187, history=startChannel,channel2, id=5f92a4ee-f5db-435b-b881-e4292cd51bdf}] at (MessageLogger.java:25)
    If I don't set the attribute, the error channel is still reset.
    Code:
    [DEBUG] [2011/28/01 11:27:31,743] [task-scheduler-1] [MessageLogger.log] [Payload=startChannel payload][Headers={errorChannel=errCh1, replyC
    hannel=nullChannel, timestamp=1296232051727, history=startChannel, id=e132f268-37f4-44ee-82ab-9e4a2a5273d4}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/28/01 11:27:31,759] [task-scheduler-1] [MessageLogger.log] [Payload=25][Headers={errorChannel=org.springframework.integration.
    core.MessagingTemplate$TemporaryReplyChannel@e2e687, replyChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChann
    el@e2e687, timestamp=1296232051758, history=startChannel,channel2, id=8220c56c-eeed-45d8-be31-e1d1c434afa6}] at (MessageLogger.java:25)
    
    [DEBUG] [2011/28/01 11:27:31,764] [task-scheduler-1] [MessageLogger.log] [Payload=after][Headers={errorChannel=errCh1, replyChannel=nullChan
    nel, timestamp=1296232051762, history=startChannel,channel2, id=991acde2-7b7d-45b7-ae9c-27f979c9a7c3}] at (MessageLogger.java:25)

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

    Default

    What do you mean it has no effect?
    Could you post your configuration?

    Here is our test just so you can validate and may be see what is wrong
    Code:
    <int:channel id="errorChannelA"/>
    	
    	<int:service-activator input-channel="errorChannelA" expression="'ERROR from errorChannelA'"/>
    		
    	<int:channel id="errorChannelB"/>
    	
    	<int:service-activator input-channel="errorChannelB" expression="'ERROR from errorChannelB'"/>
    		
    
    	<int:gateway id="testGateway" 
    	             service-interface="org.springframework.integration.gateway.InnerGatewayWithChainTests.TestGateway"
    	             default-request-channel="requestChannelA"
    	             error-channel="errorChannelA"/>
    	                    
    	<int:chain input-channel="requestChannelA">
    		<int:service-activator expression="1/(payload-5)"/>
    		<int:gateway request-channel="requestChannelB" error-channel="errorChannelB"/>
    	</int:chain>
    	
    	<int:service-activator input-channel="requestChannelB" expression="10/payload"/>
    and test code

    Code:
    @Test
    	public void testExceptionHandledByMainGateway(){
    		String reply = testGateway.echo(5);
    		assertEquals("ERROR from errorChannelA", reply);
    	}
    	
    	@Test
    	public void testExceptionHandledByInnerGateway(){
    		String reply = testGateway.echo(0);
    		assertEquals("ERROR from errorChannelB", reply);
    	}

  7. #7

    Default

    Sorry, my bad. I didn't fully tested. I just saw that the errorChannel header was still pointing to a temporary reply channel, as before, and I assumed it was bad. Fact is, if I throw an exception in channel2, it will reach the errCh1 now. (The configuration is the same as in the first post, except that there is a new error-channel attribute on the gateway.)

    Still, and I think this is more important, if I don't set an error channel on the gateway element, it will ignore an error channel header set on the message before reaching the gateway. It's good that we have the option to set the error channel on the gateway, but I think it's not enough, especially if we work with more error channels. The message may travel from gateway to gateway and we cannot always control the error channel values on them, or they may cannot point to the same error channel always. I would rather set the error channel on the message itself before passing it to a gateway, and rely on the fact that the message will reach the specified error channel if something goes wrong, no matter through how many gateways it would have to travel.

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

    Default

    Ok, let me get this straight.
    If gateway downstream does not define an error-channel, then its invocation will result in the exception (if exception is thrown somewhere downstream). However since this gateway was invoked within the flow that had also started with some other gateway (which does define an error-channel) the exception will be propagated all the way to that gateway, but since the initial gateway does define an error-channe, it will deal with that exception.
    Are you saying that it is not the case?

  9. #9

    Default

    No, I'm not saying that. In fact, the tests that I make prove that what you are saying is right. Even more, if some downstream gateway has an error channel set, it will honor that error channel, before the error channels of the upstream gateways are honored as well, which I think is a good thing, it's how I wanted.

    Something interesting here - I notice that, if I change the payload in an error channel set on some downstream gateway to something which is not an exception, then the upstream error channels are no longer receiving the message, but the gateways return the message as if no error occurred.

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

    Default

    THat was the whole point.
    IN other words it is similar to SOAP Fault concept where you always get a successful response which might contain the definition of an error.

    Glad it worked out for you.

Tags for this Thread

Posting Permissions

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