Announcement Announcement Module
Collapse
No announcement yet.
Two advice in one request-handler-advice-chain Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Two advice in one request-handler-advice-chain

    Hello,
    first of all thank you for developing request-handler-advice-chain.

    I have simply question. Is there possible to have combination of RequestHandlerRetryAdvice and ExpressionEvaluatingRequestHandlerAdvice in one request-handler-advice-chain?

    I would like to do 3 tries for some action (like for ftp otbound like in the following code) - in case of success invoke success-expression and in case of 3 failed tries invoke on error-expression but it seems to me that this configuration is doing only one try (in case of error) and then ExpressionEvaluatingRequestHandlerAdvice action (error-expression).

    Code:
    <int-ftp:outbound-channel-adapter id="ftpOutbound"
    		channel="ftpOutChannel"
    		session-factory="ftpOUT"
    		remote-directory="/foo"
    		<int-ftp:request-handler-advice-chain >
    			<bean id="retyrAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
    				<property name="retryTemplate">
    					<bean class="org.springframework.retry.support.RetryTemplate">
    						<property name="backOffPolicy">
    							<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
    								<property name="initialInterval" value="5000" />
    								<property name="multiplier" value="3" />
    							</bean>
    						</property>
    					</bean>
    				</property>
    			</bean>
    			<bean id="errorHandler" class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice" >
    				<property name="trapException" value="true"></property>
    				<property name="onSuccessExpression" value="payload.delete()" />
    				<property name="successChannel" ref="afterSuccessDeleteChannel" />
    				<property name="onFailureExpression" value="payload.renameTo(new java.io.File('/foo/failed/' + payload.getName() + '.failed'))" />
    				<property name="failureChannel" ref="afterFailRenameChannel" />
    			</bean>
    		</int-ftp:request-handler-advice-chain>
    	</int-ftp:outbound-channel-adapter>
    Thank you,
    Jakub

  • #2
    Hello, Jakub!

    Yes, it is: we already observed it and fixed: https://jira.springsource.org/browse/INT-2858.
    So, just get the latest 2.2.1.SNAPSHOT and have a good time!

    Take care,
    Artem

    Comment


    • #3
      Thank you :-),
      I have switched to 2.2.1.BUILD-SNAPSHOT and it works. Interesting note is that it works (3 attempts) only in case of definition in such order:
      Code:
      <int-ftp:request-handler-advice-chain >
         <bean id="errorHandler" class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice"/>   
         <bean id="retyrAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice"/>
      </int-ftp:request-handler-advice-chain>
      for this one:
      Code:
      <int-ftp:request-handler-advice-chain >
         <bean id="retyrAdvice" class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice"/>
         <bean id="errorHandler" class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice"/>
      </int-ftp:request-handler-advice-chain>
      there are logged always only two tries <Retry: count=0>,<Retry: count=1> and then it goes to ExpressionEvaluatingRequestHandlerAdvice (even if I use 5 attempts in retryPolicy)

      ---------------------------------------------------------------------------------------------------
      I have also one question regarding Error message which is sent to failureChannel. Please let me know whether I should create new thread for this.

      Lets say that this ftp outbound action fails due to non-exsting target path. Without spring-integration or without ExpressionEvaluatingRequestHandlerAdvice I get full stack trace with many "causes" and root cause
      java.io.IOException: Failed to write.... Server replied with: 553 Could not create file. which is quite important information.

      In my failureChannel where I use following expression I get following message:
      Code:
      expression="payload.getMessage()+' cause: '+payload.getCause()"
      
      Handler Failed cause: org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice$ThrowableHolderException: org.springframework.integration.MessagingException: Failed to invoke handler
      which has only final Exception + cause. Is there somehow possible to get root cause? BTW payload.getCause().getStackTrace().toString() did not help.

      Thank you,
      Jakub

      Comment


      • #4
        The advices are nested (chained); I am surprised to see any retries when the error handler (with trapException="true") is defined AFTER the retry advice. I'll run some tests.

        The exception should be in payload.cause.cause - but I don't think we should be exposing the ThrowableHolderException, we should be unwrapping it - again, I'll run some tests to see what's going on.

        Comment


        • #5
          I just ran some tests and it worked as expected for me; when the chain was defined with the retry advice first, and the errorHandler second (with trapException = true) I only see one attempt (count=0) because, from the perspective of the retry advice, the downstream calls were successful (the errorHandler trapped the exception).

          When I put the errorHandler first, I see the 3 attempts followed by the error going to the 'afterFailRenameChannel'.

          However, we should not be leaking the ThrowableHolderException to the outside world. I opened a new JIRA for that. https://jira.springsource.org/browse/INT-2894

          Comment


          • #6
            Thank you Gary,
            you are right - I saw <Retry: count=0>,<Retry: count=1> (when the error handler is defined AFTER the retry advice) event when trapException="false".
            --------------------------------------------------------
            Also thank you for opening of JIRA regarding Exceptions - I am trying 2.2.1-RELEASE now and payload.cause.cause.cause.cause returns the root cause . However - is there any way how to get it directly - without nesting (since for some other type exceptions the value of expression: payload.cause.cause.cause.cause does not need to exist and it will throw Expression evaluation failed)

            Regards,
            Jakub

            Comment


            • #7
              2.2.1 should be suppressing the ThrowableHolderException; can you post a full stack trace?

              Comment


              • #8
                this is what I am doing:
                Code:
                	<int:header-enricher input-channel="afterFailRenameChannel" output-channel="logChannel">
                		<int:header name="LEVEL" value="ERROR"/>
                		<int:header name="TITLE" value="FILE NOT_TRANSFERED"/>
                		<int:header name="MESSAGE" expression="'Moving of ' + payload.failedMessage.payload.absolutePath + ' to ${integration.ftp.failed.location} after failed transfer, result: '+payload.getMessage()+' cause: '+payload.cause.cause.cause.cause"/>
                	</int:header-enricher>
                payload.cause.cause.cause.cause - returns
                Code:
                java.io.IOException: Failed to write to ''/apps/soadev/ftp/inbound/platform_spring_test/write/somefile-20130128113542.dat.writing''. Server replied with: 553 Could not create file
                which is good - this is what I want but the problem is that other type of error can has different number of causes so it can returns null or throws exception like in the following:
                payload.cause.cause.cause.cause.cause - returns null
                payload.cause.cause.cause.cause.cause.cause - returns (this is reasonable since the parent cause is null)

                Comment


                • #9
                  exception is too long - I am not able to send full stackTrace

                  Code:
                  Caused by: org.springframework.integration.MessagingException: failed to transform message headers
                  	at org.springframework.integration.transformer.HeaderEnricher.transform(HeaderEnricher.java:122)
                  	at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67)
                  	... 120 more
                  Caused by: org.springframework.integration.MessageHandlingException: Expression evaluation failed: 'Moving of ' + payload.failedMessage.payload.absolutePath + ' to d:/temp/failed after failed transfer, result: '+payload.getMessage()+' cause: '+payload.cause.cause.cause.cause.cause.cause
                  	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:93)
                  	at org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor.processMessage(ExpressionEvaluatingMessageProcessor.java:67)
                  	at org.springframework.integration.transformer.HeaderEnricher$ExpressionEvaluatingHeaderValueMessageProcessor.processMessage(HeaderEnricher.java:216)
                  	at org.springframework.integration.transformer.HeaderEnricher.transform(HeaderEnricher.java:113)
                  	... 121 more
                  Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 183): Field or property 'cause' cannot be found on null
                  	at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:205)
                  	at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
                  	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
                  	at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:63)
                  	at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
                  	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
                  	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126)
                  	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:86)
                  	... 124 more

                  Comment


                  • #10
                    this is the begining
                    Code:
                    org.springframework.integration.transformer.MessageTransformationException: org.springframework.integration.MessagingException: failed to transform message headers
                    	at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:73)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:134)
                    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102)
                    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
                    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
                    	at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
                    	at org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice.evaluateFailureExpression(ExpressionEvaluatingRequestHandlerAdvice.java:169)
                    	at org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice.doInvoke(ExpressionEvaluatingRequestHandlerAdvice.java:125)
                    	at org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice.invoke(AbstractRequestHandlerAdvice.java:58)
                    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
                    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
                    	at $Proxy18.handleMessage(Unknown Source)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102)
                    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
                    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
                    	at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:216)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:200)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:165)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:159)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:141)
                    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102)
                    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
                    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
                    	at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:216)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:200)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:165)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:155)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:141)
                    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115)
                    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102)
                    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
                    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
                    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
                    	at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendMessage(AbstractReplyProducingMessageHandler.java:216)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:200)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:165)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:159)
                    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:141)
                    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
                    	at org.springframework.integration.dispatcher.BroadcastingDispatcher.invokeHandler(BroadcastingDispatcher.java:121)
                    	at org.springframework.integration.dispatcher.BroadcastingDispatcher.dispatch(BroadcastingDispatcher.java:112)
                    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)

                    Comment


                    • #11
                      I don't really need the full trace, but I do need all the "Caused by:" lines.

                      Comment


                      • #12
                        In this case it is:

                        Code:
                        org.springframework.integration.transformer.MessageTransformationException: org.springframework.integration.MessagingException: failed to transform message headers
                        	at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:73)
                        
                        ...
                        
                        Caused by: org.springframework.integration.MessagingException: failed to transform message headers
                        	at org.springframework.integration.transformer.HeaderEnricher.transform(HeaderEnricher.java:122)
                        	at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67)
                        	... 120 more
                        Caused by: org.springframework.integration.MessageHandlingException: Expression evaluation failed: 'Moving of ' + payload.failedMessage.payload.absolutePath + ' to d:/temp/failed after failed transfer, result: '+payload.getMessage()+' cause: '+payload.cause.cause.cause.cause.cause.cause
                        	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:93)
                        	at org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor.processMessage(ExpressionEvaluatingMessageProcessor.java:67)
                        	at org.springframework.integration.transformer.HeaderEnricher$ExpressionEvaluatingHeaderValueMessageProcessor.processMessage(HeaderEnricher.java:216)
                        	at org.springframework.integration.transformer.HeaderEnricher.transform(HeaderEnricher.java:113)
                        	... 121 more
                        Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 183): Field or property 'cause' cannot be found on null
                        	at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:205)
                        	at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
                        	at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
                        	at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:63)
                        	at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102)
                        	at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102)
                        	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126)
                        	at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:86)
                        	... 124 more
                        Actually I do not know whether this is real problem - I can write some method which will returns all causes and use it in my expression.

                        string c
                        Throwable cause <- from integration message

                        while(cause!=null){
                        c + = cause
                        cause = cause.getCause()
                        }
                        return c

                        regards,
                        Jakub

                        Comment


                        • #13
                          You have too many .cause parts in your expression

                          Field or property 'cause' cannot be found on null

                          Comment


                          • #14
                            If you want to handle a variable number of cause parts, add a bean that does the recursion (like you suggested), then use something like...

                            Code:
                            ...cause: '+ @causeAnalyzer.findRootCause(payload)

                            Comment

                            Working...
                            X