スレッドthisのコメントセクションで疑問を尋ねたことがあります。ExpressionEvaluatingRequestHandlerAdviceは、SpelExceptionの場合に成功と失敗の両方のチャネルにメッセージを送信します
アプリケーションをデバッグしているときに、私はいくつかのコードエラーに気がつきました。それらはバグですか、機能ですか? AdviceMessage
がSuccessChannel
に送信された後
- は
ExpressionEvaluatingRequestHandlerAdvice::evaluateSuccessExpression
では、例外がスローされます。これにより例外ペイロードが発生します。メソッドが最初に例外をスローしてはいけませんか? - 同じクラスでは、
propagateOnSuccessEvaluationFailures
がデフォルトで「偽」になっているため、例外がスローされません。それはむしろFailChannel
の目的を否定する。私はそれを「真の」外部に設定しました。あなたはこれらの背後にある思考過程を説明していただけますか?ゲイリーは、私は一般的に、エラーハンドラがエラーを処理し、呼び出し側が問題があった知る必要がないため、ポイント2のためにあなたのポイント1.を理解していない、に答えた
。一般にエラーハンドラフローが存在する場合、エラーハンドラが関与したことを呼び出し元に示すために新しい例外をスローする必要があります。真偽値は、エラーを処理し、元の例外を呼び出し元にスローする稀なインスタンスです。
このスレッドを乱雑にする代わりに、ここでその点について話し合うことができます。
ポイント2の説明はtrapException
に適用されると思います。
私の指摘を明確にするために、ExpressionEvaluatingRequestHandlerAdvice
の一部をコピーしました。 doInvoke
で
protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception {
try {
Object e = callback.execute();
if(this.onSuccessExpression != null) {
this.evaluateSuccessExpression(message);
}
return e;
} catch (Exception var7) {
Exception actualException = this.unwrapExceptionIfNecessary(var7);
if(this.onFailureExpression != null) {
Object evalResult = this.evaluateFailureExpression(message, actualException);
if(this.returnFailureExpressionResult) {
return evalResult;
}
}
if(!this.trapException) {
throw actualException;
} else {
return null;
}
}
}
private void evaluateSuccessExpression(Message<?> message) throws Exception {
boolean evaluationFailed = false;
Object evalResult;
try {
evalResult = this.onSuccessExpression.getValue(this.prepareEvaluationContextToUse((Exception)null), message);
} catch (Exception var5) {
evalResult = var5;
evaluationFailed = true;
}
if(this.successChannel == null && this.successChannelName != null && this.getChannelResolver() != null) {
this.successChannel = (MessageChannel)this.getChannelResolver().resolveDestination(this.successChannelName);
}
if(evalResult != null && this.successChannel != null) {
AdviceMessage resultMessage = new AdviceMessage(evalResult, message);
this.messagingTemplate.send(this.successChannel, resultMessage);
}
if(evaluationFailed && this.propagateOnSuccessEvaluationFailures) {
throw (Exception)evalResult;
}
}
private Object evaluateFailureExpression(Message<?> message, Exception exception) throws Exception {
Object evalResult;
try {
evalResult = this.onFailureExpression.getValue(this.prepareEvaluationContextToUse(exception), message);
} catch (Exception var6) {
evalResult = var6;
this.logger.error("Failure expression evaluation failed for " + message + ": " + var6.getMessage());
}
if(this.failureChannel == null && this.failureChannelName != null && this.getChannelResolver() != null) {
this.failureChannel = (MessageChannel)this.getChannelResolver().resolveDestination(this.failureChannelName);
}
if(evalResult != null && this.failureChannel != null) {
ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException messagingException = new ExpressionEvaluatingRequestHandlerAdvice.MessageHandlingExpressionEvaluatingAdviceException(message, "Handler Failed", this.unwrapThrowableIfNecessary(exception), evalResult);
ErrorMessage resultMessage = new ErrorMessage(messagingException);
this.messagingTemplate.send(this.failureChannel, resultMessage);
}
return evalResult;
}
callback.execute()
またはevaluateSuccessExpression
が例外をスローした場合、evaluateFailureExpression
が呼び出されます。
evaluateSuccessExpression
で、SuccessExpression
の評価中にエラーが発生した場合、例外はevalResult
に格納されます。設定されている場合、これはSuccessChannel
に送信されます。 propagateOnSuccessEvaluationFailures
がtrue
に設定されている場合は、evaluateSuccessExpression
だけがエラーをスローします。既定では「false」に設定されているため、evalResult
はスローされず、結果的にevaluateFailureExpression
によって捕捉されません。
他の要件によってpropagateOnSuccessEvaluationFailures
を '偽'に設定する必要がある場合でも、結果をSuccessChannel
に送信する前に例外をスローする必要があります。
ご意見ありがとうございます。 JIRAの問題をどのようにすることができますか? 動作変更であることに同意しますので、審査のための時間が必要です。 – Nets
ここ:https://jira.spring.io/browse/INT –