Announcement Announcement Module
Collapse
No announcement yet.
Most strange issue observed after defining "error-channel" at Gateway Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Most strange issue observed after defining "error-channel" at Gateway

    Hi

    I've faced a very strange issue while defining my spring config file and I'm still not sure of the reason (though I've managed to fix the issue).

    I'm attaching my original and modified spring config files as the post does not allow me to exceed a certain number of characters and even if I try to present only the elements I've issue with, the size limit is getting exceeded. So just to explain the issue better, I'm attaching the files.

    If you see the the <!-- Channel --> section in my original config file, not all channels defined in it are being used and also many channels that I'd defined in my various chains (as "input-channel") were not mentioned in this section.

    Though Spring never complained to me of not defining my channels before using them in chain, but for better readability I chose to remove all unwanted channels and define all the channels that are being used in my spring config file.

    The strange issue I started observing with my modified spring config file was that the "global" interceptors I'd defined were failing to get invoked. I just could not understand the reason.
    Finally, after lot of struggle, I see that the following two channels that I defined in my modified config file are causing the issue:

    <int:channel id="onlineReqRcvExceptionHandlerChannel" />
    <int:channel id="offlineReqRcvExceptionHandlerChannel" />

    These are "error-channel" that I've defined at my Gateway level and there are two separate chains that are reading these channels.

    I removed the above two channels from my <!-- Channels --> section (i.e., I removed explicitly defining them through "channel" element) and to my surprise, the global channel have started getting invoked.

    This is really puzzling me but I'm very curious to know what could be the reason behind this.

    Note - My global interceptor classes are overiding the "preSend" method.

    Thanks & Regards
    LB
    Last edited by lbvirgo; Jul 5th, 2013, 02:23 PM.

  • #2
    Can someone pls help me out in knowing the reason behind above issue ?

    Many thanks in advance.

    Best Regards
    LB

    Comment


    • #3
      Hi!
      H-m-m...
      There are a lot of your own code...
      Can you minimize configs to localize the issue?
      Sorry, now it's a bit difficult.

      Cheers,
      Artem

      Comment


      • #4
        Yes, I can.
        Let me elaborate the issue here itself:

        I've the following Gateway configuration defined:

        Code:
        	<int:gateway id="ersServiceOnlineReqRcvGateway"
        				 service-interface="com.bnym.ecs.report.service.orchestration.gateway.ERSOrchestrationSvcReqGateway"
        				 error-channel="onlineReqRcvExceptionHandlerChannel" >
        
        		<int:method name="processOnlineRequest" request-channel="ersServiceReqRcvPostValidationChannel" />
        
        	</int:gateway>
        
        	<int:gateway id="ersServiceOfflineReqRcvGateway"
        				 service-interface="com.bnym.ecs.report.service.orchestration.gateway.ERSOrchestrationSvcReqGateway"
        				 error-channel="offlineReqRcvExceptionHandlerChannel" >
        
        		<int:method name="processOfflineRequest" request-channel="ersServiceReqRcvPostValidationChannel" />
        
        	</int:gateway>
        And I've following "global" interceptors defined:

        Code:
        	<int:channel-interceptor pattern="ersServiceReqRcvPostValidationChannel, 
        									   executionSvcSubmitAdhocReqChannel,
        									   transformationSvcSubmitAdhocReqChannel,
        									   pollerSvcSubmitAdhocReqChannel,
        									   ersSvcSubmitNonAdhocReqChannel,
        									   hwdSubmitNonAdhocReqChannel,
        									   ersServiceResRcvPostValidationChannel" 
        							 order="1">
            	<bean class="com.bnym.ecs.report.service.orchestration.interceptors.MsgJSONSyntaxValidationInterceptor"/>
        	</int:channel-interceptor>
        
        	<int:channel-interceptor pattern="ersServiceReqRcvPostValidationChannel, 
        									   executionSvcSubmitAdhocReqChannel,
        									   transformationSvcSubmitAdhocReqChannel,
        									   pollerSvcSubmitAdhocReqChannel,
        									   ersSvcSubmitNonAdhocReqChannel,
        									   hwdSubmitNonAdhocReqChannel,
        									   ersServiceResRcvPostValidationChannel" 
        							 order="2">
            	<bean class="com.bnym.ecs.report.service.orchestration.interceptors.MsgMetaDataValidationInterceptor"/>
        	</int:channel-interceptor>
        The channels defined as "request-channel" on both gateway methods are explicitly defined as below:

        Code:
        	<int:channel id="ersServiceReqRcvPostValidationChannel">
        		<int:interceptors>
        			<ref bean="msgReqAuditDAOInterceptor"/>
        		</int:interceptors>     
        	</int:channel>
        	
        	<int:channel id="ersServiceResRcvPostValidationChannel">
        	    <int:interceptors>
        	        <ref bean="msgResAuditDAOInterceptor"/>
        	    </int:interceptors> 
        	</int:channel>
        If you see my gateway configuration, I've defined two customized "error-channel" on them viz., "onlineReqRcvExceptionHandlerChannel" and "offlineReqRcvExceptionHandlerChannel".

        What I'm observing is, if I define these two error channels explicitly by the <channel> tag as mentioned below,

        Code:
        	<int:channel id="onlineReqRcvExceptionHandlerChannel" />
        	<int:channel id="offlineReqRcvExceptionHandlerChannel" />
        the "global" interceptors are failing to invoke.

        On removing the above configuration (i.e., on removing their explicit definition through <channel> tag), the "global" interceptors are getting invoked.

        The "global" interceptor classes are extending ChannelInterceptorAdapter class and are overriding its "preSend" method.

        Pls note - The "request-channel"s defined on both my gateway methods have both local and global interceptors defined. The "order" of global interceptors is positive (which means, local interceptor is invoked first). I see that "local" interceptor is getting invoked well. The issue is only with the "global" interceptors.

        Hope I've made myself clear.

        Thanks & Regards
        LB

        Comment


        • #5
          Can you turn on DEBUG logging for "org.springframework.integration.channel.intercept or.GlobalChannelInterceptorBeanPostProcessor" and compare the output for both cases?

          That class is the one that applies the global interceptors and it emits debug logging that might help narrow down the problem; for example...

          logger.debug("Applying global interceptors on channel '" + beanName + "'");

          Looking at the code, I don't see why there would be any difference whether the channel was explicitly declared or not; the logging might help.

          Comment


          • #6
            I mentioned below lines in my log4j.properties:

            Code:
            log4j.logger.org.springframework.integration.channel.interceptor.GlobalChannelInterceptorBeanPostProcessor=DEBUG,interceptor
            log4j.appender.interceptor=org.apache.log4j.RollingFileAppender
            log4j.appender.interceptor.File=C:\\web\\logs\\ewb\\NTS\\ersOrcSvc\\ersOrchestrationSvc_INTERCEPTOR.log
            log4j.appender.interceptor.MaxFileSize=10MB
            log4j.appender.interceptor.MaxBackupIndex=10
            log4j.appender.interceptor.layout=org.apache.log4j.PatternLayout
            log4j.appender.interceptor.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p [%t] %c - %m%n
            But on server startup I'm getting this exception:

            ERROR [localhost-startStop-1] (ContextLoader.java:215) - Context initialization failed
            org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'org.springframework.integration.channel.intercept or.GlobalChannelInterceptorBeanPostProcessor#0': Cannot resolve reference to bean 'org.springframework.integration.channel.intercept or.GlobalChannelInterceptorWrapper#0' while setting constructor argument with key [0]; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'org.springframework.integration.channel.intercept or.GlobalChannelInterceptorWrapper#0': Cannot create inner bean 'com.bnym.ecs.report.service.orchestration.interce ptors.MsgJSONSyntaxValidationInterceptor#0' of type [com.bnym.ecs.report.service.orchestration.intercep tors.MsgJSONSyntaxValidationInterceptor] while setting constructor argument; nested exception is org.springframework.beans.factory.CannotLoadBeanCl assException: Cannot find class [com.bnym.ecs.report.service.orchestration.intercep tors.MsgJSONSyntaxValidationInterceptor] for bean with name 'com.bnym.ecs.report.service.orchestration.interce ptors.MsgJSONSyntaxValidationInterceptor#0' defined in ServletContext resource [/WEB-INF/spring/ersOrchestration-spring-config-si.xml]; nested exception is java.lang.ClassNotFoundException: com.bnym.ecs.report.service.orchestration.intercep tors.MsgJSONSyntaxValidationInterceptor
            It is unable to find the class of my global interceptor (com.bnym.ecs.report.service.orchestration.interce ptors.MsgJSONSyntaxValidationInterceptor)

            Is this a configuration issue with my local server ?

            Regards
            LB
            Last edited by Gary Russell; Jul 5th, 2013, 11:08 AM.

            Comment


            • #7
              You only get this error when you change the logging properties?

              If so, that is very weird.

              Comment


              • #8
                I did not try to start the server after removing the above configuration from log4j.properties.

                I'll do that on Monday once I'm back in office.

                In case I do not get any exception on server startup after removing the above configuration from log4j.properties than it really is weird.
                Just to confirm that it isn't related to my local server setup, I'll try to put my build in one of my "test" environments.

                Thanks & Regards
                LB

                Comment


                • #9
                  Looks like I was doing some configuration mistake in my log4j.properties earlier on and that is the reason I was getting issue on server startup. I tried it today and I did not get any issues on server startup.

                  Pls find below the details that I get from logs when I mentioned the "error-channel" explicitly vs not mentioning it explicitly :-

                  ==>When channel *is* defined explicitly

                  Application logs :

                  Attachment


                  Interceptor Logs:

                  Attachment




                  ==>When channel *is NOT* defined explicitly

                  Application logs :

                  Attachment

                  Interceptor Logs:

                  Attachment

                  If you compare the two sets of logs, you will notice that

                  1) In application logs, my global interceptors MsgJSONSyntaxValidationInterceptor and MsgMetaDataValidationInterceptor are getting invoked only when "error-channel" was not defined explicitly.

                  2) In Interceptor logs, the log messages

                  Applying global interceptors on channel 'onlineReqRcvExceptionHandlerChannel'
                  Applying global interceptors on channel 'offlineReqRcvExceptionHandlerChannel'
                  Applying global interceptors on channel 'resRcvExceptionHandlerChannel'

                  appears only when I do not define my above error-channel explicitly.

                  Can you pls help out in knowing what could be the reason for this ?

                  Best Regards
                  LB
                  Attached Files
                  Last edited by lbvirgo; Jul 8th, 2013, 04:48 AM.

                  Comment


                  • #10
                    Your title "Most Strange" is very accurate.

                    It looks like a total of 12 channels are intercepted in the second case, but not in the first.

                    Please open up a JIRA issue for this https://jira.springsource.org/browse/INT.

                    It would be very helpful if you could attach DEBUG logs for org.springframework that cover the application context initialization (in both cases). You don't need to process any messages, we just need to see the context initializing in the "works" and "doesn't work" case.

                    That way, we should be able to figure out what's happening.

                    I suspect it's something to do with BeanFactoryPostProcessor ordering but I would expect the "reverse" if that was the case (not intercepting implicit channels).

                    Most strange indeed.

                    Comment


                    • #11
                      I'll raise a JIRA tkt probably by tomorrow. For the moment pls find attached the log files you requested for.

                      You may find some application related logs in these files, you probably can ignore them.

                      Many thanks and Best Regards
                      LB

                      Comment


                      • #12
                        Hi Gary - On a totally different context, I've a requirement and I need to figure out a logic to handle it using SI framework. If I may be allowed to put it in same post, below are the details:

                        An external component invokes my application servlet by passing few details as query params. I put these query params in a Map and then invoke a method on a Gateway. I'm not expecting any response from the gateway method, hence I'm keeping its return as void.
                        However it takes considerable time for the method to return and I do not want my external component to wait until then. I just want to do a return from my servlet's doPost asap.
                        I read the reference doc and I see Asynchronous Gateway is the best fit for this requirement.

                        But I'm not clear on one thing, is it mandatory to give a return type of Future type in my gateway method even if I'm not expecting any return from the downstream ?
                        What is the solution to have the Query Param Map processed in a separate thread and have the Servlet's doPost return immediately in the calling thread (after invoking the gateway's method) without expecting any response ? Something like Future<void> method return type is possible ?

                        Thanks & Regards
                        LB

                        Comment


                        • #13
                          It is an ordering issue; for some reason, when explicitly declared, the channel is being instantiated before all the bean post processors have been instantiated.

                          2013-07-08 09:11:02,161 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Creating instance of bean 'onlineReqRcvExceptionHandlerChannel'
                          2013-07-08 09:11:02,161 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Eagerly caching bean 'onlineReqRcvExceptionHandlerChannel' to allow for resolving potential circular references
                          2013-07-08 09:11:02,177 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Invoking afterPropertiesSet() on bean with name 'onlineReqRcvExceptionHandlerChannel'
                          2013-07-08 09:11:02,177 INFO [localhost-startStop-1] org.springframework.web.context.support.XmlWebAppl icationContext - Bean 'onlineReqRcvExceptionHandlerChannel' of type [class org.springframework.integration.channel.DirectChan nel] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
                          2013-07-08 09:11:02,177 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Finished creating instance of bean 'onlineReqRcvExceptionHandlerChannel'
                          The problem seems to be that the instantiation of your "MsgMetaDataValidationInterceptor" is triggering early instantiation of other components which, in turn, triggers the instantiation of the channel (when explicitly declared). When the channel is not explicitly declared, the instantiation fails at this stage, and so all is "well".

                          2013-07-08 09:04:24,428 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Eagerly caching bean 'ersServiceOnlineReqRcvGateway' to allow for resolving potential circular references
                          2013-07-08 09:04:24,444 DEBUG [localhost-startStop-1] org.springframework.beans.factory.support.DefaultL istableBeanFactory - Ignoring bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'ersServiceOnlineReqRcvGateway': Cannot resolve reference to bean 'onlineReqRcvExceptionHandlerChannel' while setting bean property 'errorChannel'; nested exception is org.springframework.beans.factory.NoSuchBeanDefini tionException: No bean named 'onlineReqRcvExceptionHandlerChannel' is defined
                          Does your "MsgMetaDataValidationInterceptor" do a context.getBeansOfType() ??

                          If so, can you avoid it?

                          While building the interceptor post processor, we're too early in the context lifecycle and calls like that will cause early instantiation of beans that are handled by factory beans. I don't think there is anything we can do in the framework to avoid this issue.

                          As I think I mentioned in earlier replies (perhaps to another thread), interceptors are really not meant for heavy-weight processing.

                          However, you might be able to avoid this early instantiation by decoupling your logic from the global interceptor. For example, use a global wire-tap to send the message (using a direct channel) to a service-activator with your logic in it; it will still run on the same thread before the message is forwarded.

                          Comment


                          • #14
                            For your other question, just return void and make the first channel after the gateway an ExecutorChannel.

                            http://static.springsource.org/sprin...ecutor-channel

                            http://static.springsource.org/sprin...xecutorchannel

                            Comment


                            • #15
                              Does your "MsgMetaDataValidationInterceptor" do a context.getBeansOfType() ??
                              No. Its a simple bean that converts my String payload to a Java VO and then checks for values of the encapsulated instance variables. If any mandatory value does not exist, it explicitly throws a RuntimeException.

                              I don't think there is anything we can do in the framework to avoid this issue.
                              To me such things should have been taken care in framework. Moreover, nowhere in the reference doc there is a mention that interceptors should not carry any heavy-weight processing (ofcourse, my global interceptors are very light POJO).

                              Pls let me know if you still want me to raise a JIRA on this issue.

                              Regarding my other query related to Asynchronous Gateway, I'm still not very clear on the exact functionality that this Gateway provides.

                              In reference doc we have the following example:

                              Code:
                              MathServiceGateway mathService = ac.getBean("mathService", MathServiceGateway.class); // Line 1
                              Future<Integer> result = mathService.multiplyByTwo(number); // Line 2
                              // do something else here since the reply might take a moment // Line 3
                              int finalResult =  result.get(); // Line 4 (removed the TIMEOUT logic)
                              1) Does it mean that the execution of lines of code "inside" the method "multiplyByTwo" will be part of a separate thread (other than the invoking thread) ?
                              2) Is it possible to have the return type of method "multiplyByTwo" void and still call it through Async gateway ?
                              3) If the answer to question 2 is a NO, then is it possible that return type is Future<?> but I do nothing of that return ? In other words, is it mandatory to call result.get() at some point in the main code even if I'm not interested in what has been returned by the downstream ?
                              4) An extension to question 3 and with reference to the above mentioned example, I believe after Line 2, the downstream will be processed as part of separate thread. From Line 3 I believe you mean that the invoking thread can do some business logic while the other thread is processing the downstream. When Line 4 is about to get executed, does it mean that the invoking thread will keep on hanging (assuming infinite TIMEOUT period) until the downstream thread has completed its execution and returned back the Future (in a sense will it be a kind-of "aggregator" behavior)?
                              5)What will happen if instead of Line 4 I'd a "return" statement ? Will the main thread (i.e., invoked thread) execution be completed in that case irrespective of the execution status of downstream thread ?

                              Thanks to clarify.

                              Best Regards
                              LB
                              Last edited by lbvirgo; Jul 8th, 2013, 02:59 PM.

                              Comment

                              Working...
                              X