【问题标题】:ExpressionEvaluatingRequestHandlerAdvice with groovyExpressionEvaluatingRequestHandlerAdvice 与 groovy
【发布时间】:2013-02-21 18:48:49
【问题描述】:

是否可以将 Spring 集成 groovy 脚本链接到 ExpressionEvaluatingRequestHandlerAdvice bean 上的成功/失败结果?目前我有这个配置删除有效负载

<beans:bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
    <beans:property name="onSuccessExpression" value="new File(payload).delete()"/>
    <beans:property name="successChannel" ref="successChannel" />
    <beans:property name="onFailureExpression" value="new File(payload).delete()"/>
    <beans:property name="failureChannel" ref="failureChannel" />
</beans:bean>

但我想使用各种标头详细信息运行一些操作来删除有效负载并重命名和更改文件权限。 groovy 脚本可能看起来像

    <int-groovy:script>
    <![CDATA[
    def encryptedFile = new File(payload);
        encryptedFile.delete();
        def file = new File(headers['ORIGINAL_FILE']);
        def successFolder = new File(file.getParent(),'success');
        return file.renameTo(new File(successFolder, file.getName()));
        ]]>
    </int-groovy:script>
</int:transformer>

但我不确定如何将此配置链接到“成功频道”。

编辑

好的,我将两个表达式连接起来以传递原始消息,并将常规逻辑链接到转换器

<!-- handle ftp outcome -->
        <beans:bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
            <beans:property name="onSuccessExpression" value="payload"/>
            <beans:property name="successChannel" ref="successChannel"/>
            <beans:property name="onFailureExpression" value="payload"/>
            <beans:property name="failureChannel" ref="failureChannel"/>
        </beans:bean>
    </int-ftp:request-handler-advice-chain>
</int-ftp:outbound-channel-adapter>

<int:transformer input-channel="successChannel" output-channel="outputB">
    <int-groovy:script>
    <![CDATA[
        def encryptedFile = new File(payload);
        encryptedFile.delete();
        def file = new File(headers['ORIGINAL_FILE']);
        def successFolder = new File(file.getParent(),'success');
        return file.renameTo(new File(successFolder, file.getName()));
        ]]>
    </int-groovy:script>
</int:transformer>

但如果我使用 'payload' 或 '#root' 会得到这个异常

Caused by: org.springframework.integration.MessageHandlingException: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.io.File(org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:76)
    at org.springframework.integration.transformer.AbstractMessageProcessingTransformer.transform(AbstractMessageProcessingTransformer.java:56)
    at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:67)
    ... 56 more
Caused by: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: java.io.File(org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException)
    at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1459)
    at groovy.lang.MetaClassImpl.invokeConstructor(MetaClassImpl.java:1375)
    at org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite.callConstructor(MetaClassConstructorSite.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
    at groovy.lang.run(groovy.lang.Script:3)
    at org.springframework.scripting.groovy.GroovyScriptFactory.executeScript(GroovyScriptFactory.java:247)
    at org.springframework.scripting.groovy.GroovyScriptFactory.getScriptedObject(GroovyScriptFactory.java:185)
    at org.springframework.integration.groovy.GroovyScriptExecutingMessageProcessor.executeScript(GroovyScriptExecutingMessageProcessor.java:88)
    at org.springframework.integration.scripting.AbstractScriptExecutingMessageProcessor.processMessage(AbstractScriptExecutingMessageProcessor.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:84)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
    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.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:227)
    at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:127)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:73)
    ... 58 more

这似乎表明传递的是“ExpressionEvaluatingRequestHandlerAdvice”bean 引用而不是文件名?

编辑 - 第 2 天

所以我根据 Gary 的评论更新了示例,并将“inputMessage.payload”用于成功通道,“payload.failedMessage”用于失败通道。配置如下所示

<int-ftp:outbound-channel-adapter 
    id="ftpOutbound" 
    channel="inputB"        
    cache-sessions="false"
    remote-directory="/"
    session-factory="ftpClientFactory">
    <int-ftp:request-handler-advice-chain>
        <!-- handle three retry attempts -->
        <beans:bean class="org.springframework.integration.handler.advice.RequestHandlerRetryAdvice">
            <beans:property name="retryTemplate">
                <beans:bean class="org.springframework.retry.support.RetryTemplate">
                    <beans:property name="backOffPolicy">
                        <beans:bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
                            <beans:property name="initialInterval" value="5000" />
                            <beans:property name="multiplier" value="3" />
                        </beans:bean>
                    </beans:property>
                </beans:bean>
            </beans:property>
        </beans:bean>
        <!-- handle ftp outcome -->
        <beans:bean class="org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice">
            <beans:property name="onSuccessExpression" value="payload"/>
            <beans:property name="successChannel" ref="successChannel"/>
            <beans:property name="onFailureExpression" value="payload"/>
            <beans:property name="failureChannel" ref="failureChannel"/>
        </beans:bean>
    </int-ftp:request-handler-advice-chain>
</int-ftp:outbound-channel-adapter>

<int:transformer input-channel="successChannel" output-channel="outputB">
    <int-groovy:script>
    <![CDATA[
        println('successChannel');
        def file = new File(inputMessage.headers['ORIGINAL_FILE']);
        def successFolder = new File(file.getParent(),'success');
        file.renameTo(new File(successFolder, file.getName()));

        def encryptedFile = inputMessage.payload;
        encryptedFile.delete();
        ]]>
    </int-groovy:script>
</int:transformer>

<int:transformer input-channel="failureChannel" output-channel="outputB">
    <int-groovy:script>
    <![CDATA[
        println('failChannel');
        def file = new File(payload.failedMessage.headers['ORIGINAL_FILE']);
        def failedFolder = new File(file.getParent(),'failed');
        file.renameTo(new File(failedFolder, file.getName()));

        def encryptedFile = payload.failedMessage.payload;
        encryptedFile.delete();
        ]]>
    </int-groovy:script>
</int:transformer>

但似乎通知处理程序被调用了 3 次,而不是在第一次成功的 FTP 传输后停止。我的“onSucessExpression”逻辑不正确吗?

2013-02-21 10:40:39,588 INFO  [org.springframework.integration.ftp.session.FtpSession] (main) File has been successfully transfered to: /SEPA.enc.writing
2013-02-21 10:40:39,591 INFO  [org.springframework.integration.ftp.session.FtpSession] (main) File has been successfully renamed from: /SEPA.enc.writing to /SEPA.enc
2013-02-21 10:40:39,591 DEBUG [org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice] (main) Unable to attempt conversion of Message payload types. Component 'org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice#2e1551b0' has no explicit ConversionService reference, and there is no 'integrationConversionService' bean within the context.
2013-02-21 10:40:39,594 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'successChannel', message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443239593, id=3adf23f7-c428-485a-9da5-839923a915fd}]
2013-02-21 10:40:39,594 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@7219d6af received message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443239593, id=3adf23f7-c428-485a-9da5-839923a915fd}]
successChannel
2013-02-21 10:40:40,164 DEBUG [org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice] (main) Unable to attempt conversion of Message payload types. Component 'org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice#2e1551b0' has no explicit ConversionService reference, and there is no 'integrationConversionService' bean within the context.
2013-02-21 10:40:40,165 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'failureChannel', message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443240165, id=596c3a78-493b-45bf-b9ca-c56dab15e318}]
2013-02-21 10:40:40,165 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@4c4b11e9 received message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443240165, id=596c3a78-493b-45bf-b9ca-c56dab15e318}]
failChannel
2013-02-21 10:40:45,218 DEBUG [org.springframework.integration.file.remote.handler.FileTransferringMessageHandler] (main) org.springframework.integration.file.remote.handler.FileTransferringMessageHandler#0 received message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443239551, id=73da6c1f-8658-4397-ab57-ea7591e284da, ORIGINAL_FILE=C:\projects\spring-integration\src\test\resources\citi\SEPA.xml}]
2013-02-21 10:40:45,218 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'successChannel', message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443245218, id=96c0ed36-0eb9-4bab-abff-84d63ff91d80}]
2013-02-21 10:40:45,218 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@7219d6af received message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443245218, id=96c0ed36-0eb9-4bab-abff-84d63ff91d80}]
successChannel
2013-02-21 10:40:45,220 DEBUG [org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice] (main) Unable to attempt conversion of Message payload types. Component 'org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice#2e1551b0' has no explicit ConversionService reference, and there is no 'integrationConversionService' bean within the context.
2013-02-21 10:40:45,220 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'failureChannel', message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443245220, id=a63c7877-29f6-46b2-96fc-35ad84589a82}]
2013-02-21 10:40:45,220 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@4c4b11e9 received message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443245220, id=a63c7877-29f6-46b2-96fc-35ad84589a82}]
failChannel
2013-02-21 10:41:00,227 DEBUG [org.springframework.integration.file.remote.handler.FileTransferringMessageHandler] (main) org.springframework.integration.file.remote.handler.FileTransferringMessageHandler#0 received message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443239551, id=73da6c1f-8658-4397-ab57-ea7591e284da, ORIGINAL_FILE=C:\projects\spring-integration\src\test\resources\citi\SEPA.xml}]
2013-02-21 10:41:00,227 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'successChannel', message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443260227, id=e16fb6be-e2c6-4c6e-bc99-e2e4fda9f735}]
2013-02-21 10:41:00,227 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@7219d6af received message: [Payload=C:\projects\spring-integration\src\test\resources\citi\SEPA.enc][Headers={timestamp=1361443260227, id=e16fb6be-e2c6-4c6e-bc99-e2e4fda9f735}]
successChannel
2013-02-21 10:41:00,229 DEBUG [org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice] (main) Unable to attempt conversion of Message payload types. Component 'org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice#2e1551b0' has no explicit ConversionService reference, and there is no 'integrationConversionService' bean within the context.
2013-02-21 10:41:00,229 DEBUG [org.springframework.integration.channel.DirectChannel] (main) preSend on channel 'failureChannel', message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443260229, id=187a95ad-ffdd-4151-9e02-e94e684f6dec}]
2013-02-21 10:41:00,229 DEBUG [org.springframework.integration.transformer.MessageTransformingHandler] (main) org.springframework.integration.transformer.MessageTransformingHandler@4c4b11e9 received message: [Payload=org.springframework.integration.handler.advice.ExpressionEvaluatingRequestHandlerAdvice$MessageHandlingExpressionEvaluatingAdviceException: Handler Failed][Headers={timestamp=1361443260229, id=187a95ad-ffdd-4151-9e02-e94e684f6dec}]
failChannel
2013-02-21 10:41:00,242 INFO  [org.springframework.integration.endpoint.EventDrivenConsumer] (Thread-1) Removing {transformer} as a subscriber to the 'inputA' channel

【问题讨论】:

    标签: spring-integration


    【解决方案1】:

    onSuccessChannel 上发送的消息是一个AdviceMessage,其中包含payload 中的表达式评估结果和inputMessage 中的入站消息。

    只需将"'foo'" 用作onSuccessExpression

    然后将您的&lt;transformer/&gt; 订阅到successChannel

    您可以使用payload.inputMessage 获取对消息的引用。

    或者,使用"#root"作为表达式,原始消息将在payload(以及inputMessage)中。

    编辑:

    failureChannel 上的消息是 ErrorMessageMessageHandlingExpressionEvaluatingAdviceException payload。此异常有 3 个属性 failedMessagecauseevalResult

    请注意,在您的“成功”转换器中,这不起作用...

    def file = new File(headers['ORIGINAL_FILE']);

    因为headers 指的是AdviceMessage 标头;你需要inputMessage.headers[...

    在故障变压器上,您需要payload.failedMessage.headers[...

    【讨论】:

    • 谢谢 - 接线工作正常,但现在得到一个奇怪的类演员 excpetion
    • 基于异常(试图构造一个以异常为参数的文件),看起来这是在“onFailure”分支中。发生故障时,故障通道上的消息是带有 MessageHandlingExpressionEvaluatingAdviceException 有效负载的 ErrorMessage。有效负载有 3 个属性 failedMessage、cause 和 evalResult。
    • 谢谢,现在两种不同的消息类型用于成功和失败案例是有意义的。一旦第一次成功操作发生后,仍然坚持停止建议链 - groovy 脚本是否应该返回特定代码?
    • 只需将输出通道设置为“nullChannel”即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2023-03-17
    • 2011-11-25
    • 2018-01-06
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多