Announcement Announcement Module
Collapse
No announcement yet.
A "gateway" in the middle of a "chain" resets the error channel header Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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.

    Comment


    • #3
      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.

      Comment


      • #4
        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, 10:22 AM.

        Comment


        • #5
          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)

          Comment


          • #6
            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);
            	}

            Comment


            • #7
              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.

              Comment


              • #8
                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?

                Comment


                • #9
                  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.

                  Comment


                  • #10
                    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.

                    Comment


                    • #11
                      Thank you, I had the same problem for weeks now.

                      Comment


                      • #12
                        Coming back to this, it looks like in the version 2.0.2.BUILD-SNAPSHOT a gateway in a chain is not honoring the default error channel. You have to set it explicitly in order to have the message reach the errorChannel. For example, in the following configuration I have "processor" throw an exception:

                        Code:
                          <int:chain input-channel="errorChannel">
                            <int:service-activator ref="logger"/>
                          </int:chain>
                        
                          <int:chain input-channel="channel1">
                            <int:service-activator ref="logger"/>
                            <int:service-activator expression="'start channel 1'"/>
                            <int:gateway request-channel="channel2" />
                            <int:service-activator expression="'end channel 1'"/>
                            <int:service-activator ref="logger"/>
                          </int:chain>
                        
                          <int:chain input-channel="channel2">
                            <int:service-activator ref="logger"/>
                            <int:service-activator ref="processor"/>
                            <int:service-activator ref="logger"/>
                          </int:chain>
                          
                          <int:inbound-channel-adapter channel="channel1"
                            expression="'start payload'">
                            <int:poller fixed-rate="10000"/>
                          </int:inbound-channel-adapter>
                        
                          <bean id="processor" class="test.Processor"/>
                        The message does not reach errorChannel. It just disappears. If I change the line
                        Code:
                            <int:gateway request-channel="channel2" />
                        with
                        Code:
                            <int:gateway request-channel="channel2" error-channel="errorChannel"/>
                        then the message can be seen reaching errorChannel.

                        Comment


                        • #13
                          When you say disappear do you simply mean it doesn't go to the default errorChannel or you mean it is swallowed?
                          If first, then it is intentional since the default behavior of the gateway is to throw exception back to the caller.

                          If second, then i don't think its possible based on the tests that we just added:
                          http://git.springsource.org/spring-i...03ad939560ecf5

                          There you can see that I've added two more test cases testing for scenario where there is no error-channel on the inner gateway but one exists on the outer as well as scenario where there is no error-channels at all and as you can see there is expectation on that test to fail with MessagingException

                          Comment


                          • #14
                            When you say disappear do you simply mean it doesn't go to the default errorChannel or you mean it is swallowed?
                            If first, then it is intentional since the default behavior of the gateway is to throw exception back to the caller.

                            If second, then i don't think its possible based on the tests that we just added:
                            http://git.springsource.org/spring-i...03ad939560ecf5

                            There you can see that I've added two more test cases testing for scenario where there is no error-channel on the inner gateway but one exists on the outer as well as scenario where there is no error-channels at all and as you can see there is expectation on that test to fail with MessagingException

                            Comment


                            • #15
                              I mean it doesn't go to the default errorChannel AND it is swallowed.

                              There is no caller in this case, because it is about an asynchronous flow started with by an inbound-channel-adapter with a poller. From what I understand, in such cases the exception should be routed to the error channel - the default error channel if no other is set explicitely. This doesn't seem to happen, unless I explicitly set the error channel to the default errorChannel.

                              Maybe your tests are about a stand-alone gateway, not one embedded in a chain (sorry, I don't have time to look over them now). I am talking about a gateway embedded in a chain. BTW, maybe it is not a good idea to have the same term "gateway" for both of them, it's kind of confusing.

                              Comment

                              Working...
                              X