2017-12-12 21 views
0

スレッドthisのコメントセクションで疑問を尋ねたことがあります。ExpressionEvaluatingRequestHandlerAdviceは、SpelExceptionの場合に成功と失敗の両方のチャネルにメッセージを送信します

アプリケーションをデバッグしているときに、私はいくつかのコードエラーに気がつきました。それらはバグですか、機能ですか? AdviceMessageSuccessChannelに送信された後

  1. ExpressionEvaluatingRequestHandlerAdvice::evaluateSuccessExp‌​ressionでは、例外がスローされます。これにより例外ペイロードが発生します。メソッドが最初に例外をスローしてはいけませんか?
  2. 同じクラスでは、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に送信されます。 propagateOnSuccessEvaluationFailurestrueに設定されている場合は、evaluateSuccessExpressionだけがエラーをスローします。既定では「false」に設定されているため、evalResultはスローされず、結果的にevaluateFailureExpressionによって捕捉されません。

他の要件によってpropagateOnSuccessEvaluationFailuresを '偽'に設定する必要がある場合でも、結果をSuccessChannelに送信する前に例外をスローする必要があります。

答えて

0

あなたはポイントがあると思います。 問題についてJIRAを挙げてください。私たちはその論理ブロックを改訂します。一般的に私は、最初にすべての再襲撃を確認し、その後にその例外をsuccessChannelに送信することを確認する方が良いということに同意します。

申し訳ありませんが、解決方法はありません(独自の解決方法を除いて)。すぐに修正することはできません。これは動作が変更されるためです。誰かがこの状況を実際に頼りにしている可能性があります。

ここでもポイントがあるので、propagateOnSuccessEvaluationFailuresのデフォルトを改訂することもできます。しかし、再び:次のバージョンでのみ作成できます。

+0

ご意見ありがとうございます。 JIRAの問題をどのようにすることができますか? 動作変更であることに同意しますので、審査のための時間が必要です。 – Nets

+0

ここ:https://jira.spring.io/browse/INT –

関連する問題