2016-08-31 8 views
1

シナリオになる可能性があります:私の期待はバッチで10データポイントになる可能性があります。{失敗した5、成功した5}かsthの応答を出したいと思います。春の統合errorChannel、エラーハンドル

私のロジックは、バッチをデータ要素に分割して検証することです。
検証が成功すると、aggreagtorに送信されます。
検証に失敗すると、エラーがスローされ、エラーチャネルで取り上げられます。

recipient-list-router errorChannelをinputChannelにして、2つのフィルタを接続します。目的は、直接的に応答を送信するためのフィルタリングです(ユーザー入力とは無関係 - サーバーエラーなど)。クライアント側のエラーはアグリゲータに送られてレスポンスを作成します。

ロジックに問題はありますか? アグリゲーターの後にservice-activatorを使用して結果を構築すると、「応答メッセージは受信されましたが、受信スレッドはすでに応答を受け取りました」という問題があります。このサービスアクチベータはreplyChannelに接続しています。すでにこのチャネルに送信されているメッセージがあるようですか?

私は「誤差フィルタが」replyChannelに接続した後にのみ、このサービスベーターおよびサーバーのエラー枝私の統合作業の流れを確認し(ただし、ハンドルが呼び出されることはありません。)間違った

何か? BTW、受信者リストルータまたは他のタイプのエンドポイントがerrorChannelに接続できますか? ?またはそれは私がすべてオンラインの例で見たものとして、サービス活性化因子である必要があります(しかし、彼らは本当に簡単な例です。)

サンプルXML

<int:gateway id="myGateway" service-interface="someGateway" default-request-channel="splitChannel" error-channel="errorChannel" default-reply-channel="replyChannel" async-executor="MyThreadPoolTaskExecutor"/> 

<int:splitter input-channel="splitChannel" output-channel="transformChannel" method="split"> 
    <bean class="Splitter" /> 
</int:splitter> 

<int:transformer id="transformer" input-channel="transformChannel" method="transform" output-channel="aggregateChannel"> 
    <bean class="Transformer"/> // this may throw the validation error (filter_ErrorType_1), if it cannot transform 
</int:transformer> 

<int:aggregator id="aggregator" 
    input-channel="aggregateChannel" 
    output-channel="createAnswerChannel" 
    method="aggregate"> 
    <bean class="MyAggregator" /> 
</int:aggregator> 

<int:recipient-list-router id="myErrorRouter" input-channel="errorChannel"> 
    <int:recipient channel="filter_ErrorType_1"/> 
    <int:recipient channel="filter_ErrorType_2"/> 
    <int:recipient channel="filter_ErrorType_3"/> 
</int:recipient-list-router> 

<int:filter input-channel="filter_ErrorType_1" output-channel="aggregateChannel" method="accept"></int:filter> 
<int:filter input-channel="filter_ErrorType_2" output-channel="createErrorAnswerChannel" method="accept"></int:filter> 
<int:filter input-channel="filter_ErrorType_3" output-channel="createErrorAnswerChannel" method="accept"></int:filter> 

<int:service-activator input-channel='createErrorAnswerChannel' output-channel="replyChannel" method='buildError'> 
    <bean class="AnswerBuilder"/> 
</int:service-activator> 

<int:service-activator input-channel='createAnswerChannel' output-channel="replyChannel" method='build'> 
    <bean class="AnswerBuilder"/> 
</int:service-activator> 

はフォローアップ:

<int:gateway id="myGateway" service-interface="someGateway" default-request-channel="splitChannel" error-channel="errorChannel" default-reply-channel="replyChannel" async-executor="MyThreadPoolTaskExecutor"/> 

<int:splitter input-channel="splitChannel" output-channel="transformChannel" method="split"> 
    <bean class="Splitter" /> 
</int:splitter> 

<int:transformer id="transformer1" input-channel="toTransformer1" method="transform" output-channel="toTransformer2"> 
    <bean class="Transformer1"/> // this may throw the validation error (filter_ErrorType_1), if it cannot transform 
</int:transformer> 

<int:transformer id="transformer2" input-channel="toTransformer2" method="transform" output-channel="toTransformer3"> 
    <bean class="Transformer2"/> // this may throw the validation error (filter_ErrorType_2), if it cannot transform 
</int:transformer> 

<int:transformer id="transformer3" input-channel="toTransformer3" method="transform" output-channel="aggregateChannel"> 
    <bean class="Transformer3"/> // this may throw the validation error (filter_ErrorType_3), if it cannot transform 
</int:transformer> 

??? 
// seems like you are proposing to have one gateway for each endpoint that may throw error. 
// but in this case, take transfomer 1 for example, I cannot output the gateway directly to aggregate channel since for valid data it has to go to transformer 2 
// but the failed message throwed by the error handler cannot pass transformer 2 because of afterall this is a error message not a valid data for transformer 2 
// <int:service-activator input-channel="toTransformer1" output-channel="toTransformer2" ref="gateway1"/> 

// <int:gateway id="gateway1" default-request-channel="toTransformer1" error-channel="errorChannel1"/> 

// <int:transformer id="transformer" input-channel="toTransformer1" method="transform"> 
//  <bean class="Transformer"/> // this may throw the validation error (filter_ErrorType_1), if it cannot transform 
// </int:transformer> 

// how to deal with this problem? 




<int:service-activator input-channel='createErrorAnswerChannel' output-channel="replyChannel" method='buildError'> 
    <bean class="AnswerBuilder"/> 
</int:service-activator> 

<int:service-activator input-channel='createAnswerChannel' output-channel="replyChannel" method='build'> 
    <bean class="AnswerBuilder"/> 
</int:service-activator> 

私は実際に複雑なロジックを持っていますが、ここでは変圧器123を使用しています。

答えて

3

あなたの質問は不明です。今後、より具体的な情報を提供してください。いくつかの設定とStackTraceまたはログも便利です。

<gateway>のフローの始めには、error-channelが設定されていると思います。だからあなたはReply message received but the receiving thread has already received a replyを受け取っています。

あなたの質問にこれらの言葉がないので、確信が持てません。右?

あなたはそこerrorChannelヘッダに依存しており、ゲートウェイの場合はerrorChannelヘッダがreplyChannelと同じであり、そしてそれはTemporaryReplyChannelですので、最終的replyのために戻って来ることができない - ワンショットの使用チャネルのみのため操作。

あなたの設定やコードはありませんので、適切に対応することはできません。

私はあなたがservice-activator経由中間流れgatewayを必要とします<gateway>

<service-activator id="gatewayTestService" input-channel="inputChannel" 
      output-channel="outputChannel" ref="gateway"/> 

<gateway id="gateway" default-request-channel="requestChannel" error-channel="myErrorChannel"/> 

または<chain>しかない検証とキャッチエラーを実行し、障害のために所望の応答を返すように。そのservice-activatorは、後で<aggregator>にそれらをすべて送信できます。この場合、<aggregator>はゲートウェイに正しく返信することができます。

EDIT

  1. errorChannelは、任意のインテグレーション場所からすべてのエラーメッセージをキャッチするデフォルトのグローバルBeanの名前です。詳細はhttp://docs.spring.io/spring-integration/reference/html/configuration.html#namespace-errorhandlerをご覧ください。

したがって、myErrorRouterはすべてのエラーを処理する予定なので、その名前はあなたのユースケースでは完全に悪いです!

    1. <int:recipient-list-router>ない selectorが存在しない場合、それは selectorを通過する場合、またはすべての受信者にメッセージを送信します。

    2. でない場合は<gateway>default-reply-channelは必要ありません。 output-channeldefinedがない場合に機能するreplyChannelヘッダーを使用できます。

    3. 私は<service-activator><gateway>話していることの前にはかなり簡単です、あなたの<transformer><splitter>後:

      <int:service-activator input-channel="transformChannel" 
            output-channel="aggregateChannel" ref="gateway"/> 
      
      <int:gateway id="gateway" default-request-channel="transformChannel" error-channel="validationErrorChannel"/> 
      
      <int:transformer id="transformer" input-channel="transformChannel" method="transform"> 
          <bean class="Transformer"/> // this may throw the validation error (filter_ErrorType_1), if it cannot transform 
      </int:transformer> 
      

    だから、splitterservice-activatorにアイテムを送信します。それはメッセージgatewaytransformererror-channel正確に1つの項目のために進行します。 transformerは、前のgatewayとまったく同じreplyChannelへの回答です。何らかの例外がスローされた場合は、validationErrorChannelプロセスによって処理されます。補償メッセージで返信する必要があります。そのメッセージはservice-activatorに送信されます。最後にservice-activatoraggregateChannelに結果を送信します。検証が良いかどうかは、service-activatorのブラックボックスです。

    ほんの少し役に立ちます。

    EDIT2

    私はあなたが私はあなたのコードにアドバイス受け入れ、それにもかかわらず、それは私がそれを見る方法ですされていないことをがっかり:

    <int:gateway id="myGateway" service-interface="someGateway" default-request-channel="splitChannel" 
          async-executor="MyThreadPoolTaskExecutor" /> 
    
    <int:splitter input-channel="splitChannel" output-channel="transformChannel" method="split"> 
        <bean class="Splitter" /> 
    </int:splitter> 
    
    <int:service-activator input-channel="validateChannel" output-channel="aggregateChannel" 
         ref="validateGateway"/> 
    
    <gateway id="validateGateway" default-request-channel="toTransformer1" error-channel="myErrorChannel"/> 
    
    <chain input-channel="toTransformer1"> 
        <int:transformer method="transform"> 
         <bean class="Transformer1" /> 
        </int:transformer> 
        <int:transformer method="transform"> 
         <bean class="Transformer2" /> 
        </int:transformer> 
        <int:transformer method="transform"> 
         <bean class="Transformer3" /> 
        </int:transformer> 
    </chain> 
    
    
    <int:service-activator input-channel="myErrorChannel" method="buildError"> 
        <bean class="AnswerBuilder" /> 
    </int:service-activator> 
    
    <int:aggregator id="aggregator" 
           input-channel="aggregateChannel" 
           output-channel="createAnswerChannel" 
           method="aggregate"> 
        <bean class="MyAggregator" /> 
    </int:aggregator> 
    
    <int:service-activator input-channel='createAnswerChannel' method='build'> 
        <bean class="AnswerBuilder" /> 
    </int:service-activator> 
    

    注意し、どのように私チェーン変圧器。したがって、すべての変圧器用に1つのゲートウェイがあり、いずれかのエラーがmyErrorChannelのエラー処理のためにゲートウェイに送信されます。

  • +0

    ご迷惑をおかけして申し訳ございませんが、私はをerror-channel = "errorChannel"に設定しています。この問題は後ほどxmlスニペットで更新します。 – edi

    +0

    は、返信チャネルとエラーチャネルが同じである可能性があります。エラーが発生した場合、errorChannelに例外が送信され、受信済みとしてマークされますが、その後も処理を続けます(エラーメッセージを他のエンドポイント私はアグリゲータの結果を返信チャンネルに送ると、すでに受け取ったsthについて文句を言うでしょうか?これは、ゲートウェイでreplyChannelとは異なるerrorChannelを作成することを意味しますか?それは可能ですか? – edi

    +0

    はい、そうです。彼らは本当に同じオブジェクトです。申し訳ありませんが私は明確でない場合。ゲートウェイ上の 'error-channel'は、同じオブジェクトである' replyChannel'または 'errorChannel'ヘッダ内のメッセージを受信した後でのみ動作します。 'replyChannel'と' errorChannel'は1つのメッセージに対してのみ、そして1つの応答に対しては 'TemporaryReplyChannel'であることを理解する必要があります。 –