从 ExpressionEvaluatingRequestHandlerAdvice 抛出的异常触发适配器上的错误处理程序处理程序

Exception thrown from ExpressionEvaluatingRequestHandlerAdvice triggers error handler handler on Adapter

我在我的“MessageHandler”上设置了一个建议

@ServiceActivator(inputChannel = "outbound",adviceChain = "expressionAdvice")
public MessageHandler...

并将其配置为:

@Bean
public ExpressionEvaluatingRequestHandlerAdvicer expressionAdvice() {
    ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
    advice.setFailureChannelName("failure");          
    return advice;
}

failure 处理程序中我解析并检测错误

 @ServiceActivator(inputChannel = "failure")
    public void handleFailures(Message<?> message)  {
        ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException adviceException = (ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException) message.getPayload();
        Throwable cause = adviceException.getCause().getCause().getCause();

对于特定错误,我正在执行一些操作并恢复流程。
但是对于特定的错误类型,我只是记录错误并继续,对于其他类型,我重新抛出异常以重试。

这有效,但有一个副作用,这个 throw Exception 触发了 ServiceActivator,它是在适配器 MessageProducerSupport.setErrorChannelName 上设置的。

@ServiceActivator(inputChannel = "onerror")

它完成了工作,但我想避免调用它,只是为了重试而不去这个处理程序。

我确实需要这个处理程序来捕获来自源通道的其他类型的错误。

查看 ExpressionEvaluatingRequestHandlerAdvice 上的这个选项:

/**
 * If true, any exception will be caught and null returned.
 * Default false.
 * @param trapException true to trap Exceptions.
 */
public void setTrapException(boolean trapException) {

文档中的更多信息:https://docs.spring.io/spring-integration/docs/current/reference/html/messaging-endpoints.html#message-handler-advice-chain

更新

对于条件异常“陷阱”,您需要考虑在您的 failure 频道子流程中实现一个逻辑。但是 trapException 仍然必须是 true.

这是我们目前在 ExpressionEvaluatingRequestHandlerAdvice:

中的逻辑
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) {
    try {
        Object result = callback.execute();
        if (this.onSuccessExpression != null) {
            evaluateSuccessExpression(message);
        }
        return result;
    }
    catch (RuntimeException e) {
        Exception actualException = unwrapExceptionIfNecessary(e);
        if (this.onFailureExpression != null) {
            Object evalResult = evaluateFailureExpression(message, actualException);
            if (this.returnFailureExpressionResult) {
                return evalResult;
            }
        }
        if (!this.trapException) {
            if (e instanceof ThrowableHolderException) { // NOSONAR
                throw (ThrowableHolderException) e;
            }
            else {
                throw new ThrowableHolderException(actualException); // NOSONAR lost stack trace
            }
        }
        return null;
    }
}

因此,我们捕获了 callback.execute() 的异常并在 evaluateFailureExpression() 中处理它(它可能只是将 ErrorMessage 发送到提到的 failureChannel)。这样的 this.messagingTemplate.send(this.failureChannel, errorMessage); 没有包装到 try..catch 中,因此如果您从错误处理流程中重新抛出异常,它将被冒泡到主流中。