2016-12-07 7 views
2

ので、セットアップは以下の通りです:このスレッドの実行中にSpring統合およびJDBC

<tx:advice id="txAdvice2" transaction-manager="dataSourceTransactionManager"> 
    <tx:attributes> 
     <tx:method name="*" rollback-for="Throwable" no-rollback-for="ListenerExecutionFailedException"/> 
    </tx:attributes> 
</tx:advice> 

<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter" 
            channel-transacted="true" 
            advice-chain="txAdvice2" /> 

<int:chain input-channel="input-channel" output-channel="output-channel"> 
    <int:service-activator ref="h1Handler" method="handle" /> 
    <int:service-activator ref="h2Handler" method="handle" /> 
    <int:service-activator ref="h3Handler" method="handle" /> 
    <int:splitter /> 
</int:chain> 

<int-amqp:outbound-channel-adapter channel="output-channel" exchange-name="outputit" amqp-template="rabbitTemplate" /> 

もし(すべてこのチェーンamqpINプロセス-amqpOUTはシングルスレッドで実行SHOLDので)私はListenerExecutionFailedExceptionを投げます、 dataSourceTransactionManagerはコミットを行いますが、例外が伝播されるため、amqpはメッセージを再キューに入れます。

は、どのように私は、この場合のように成功したメッセージをACKにウサギを伝えることができますか?

また、内部例外はRuleBasedTransactionAttributeで検査されない「原因」属性にのみ格納されるため、ロールバックなしの属性の実際の例外クラスを入れなければならないことがわかりました。

もう一つ、私が作る場合は、このような設定:RuleBasedTransactionAttributeは全く考慮されていないと私は、ロールバックのためには、正しく設定されていない場合でもdataSourceTransactionManagerは常にロールバックされている

<int-amqp:inbound-channel-adapter channel="input-channel" queue-names="probni" message-converter="jsonMessageConverter" 
            channel-transacted="true" 
            transaction-manager="dataSourceTransactionManager" 
            transaction-attribute="transactionAttribute" /> 

transactionAttribute。

ありがとうございます!

答えて

2

あなたはリスナーコンテナ( あなたは、外部の容器を構成し、 container属性 内の参照を提供しなければならない)にカスタムErrorHandlerを追加することができます。

private boolean isCauseFatal(Throwable cause) { 
     return cause instanceof MessageConversionException 
       || cause instanceof org.springframework.messaging.converter.MessageConversionException 
       || cause instanceof MethodArgumentNotValidException 
       || cause instanceof MethodArgumentTypeMismatchException 
       || cause instanceof NoSuchMethodException 
       || cause instanceof ClassCastException 
       || isUserCauseFatal(cause); 
    } 

は、デフォルトDefaultExceptionStrategyをサブクラス化し、にあなたの原因(複数可)を追加することができ、バージョン1.6.4以降で:

は、デフォルトのエラーハンドラは致命的として、特定のLEFE原因の例外を考慮DefaultExceptionStrategyConditionalRejectingErrorHandlerですisUserCauseFatal()

1.6.4前にあなた自身のFatalExceptionStrategy(またはエラーハンドラの実装)を提供する必要がありました。致命的な原因を

、ハンドラは、NACKにコンテナ(およびいない再キューイング)メッセージを伝えるAmqpRejectAndDontRequeueExceptionをスロー。ところで

EDIT

、あなたは例外をラップするための必要はありません、コンテナはあなたのためにそれを行います...

protected Exception wrapToListenerExecutionFailedExceptionIfNeeded(Exception e, Message message) { 
    if (!(e instanceof ListenerExecutionFailedException)) { 
     // Wrap exception to ListenerExecutionFailedException. 
     return new ListenerExecutionFailedException("Listener threw exception", e, message); 
    } 
    return e; 
} 

EDIT2

私の間違いは、error-handler属性を使ってErrorHandlerを指定することができます。

EDIT3

また、単に(LEFEにラップされます)AmqpRejectAndDontRequeueExceptionを投げます。

+0

あなたは例外をラップする必要はありません。私の編集を参照してください。また、 'error-handler'属性を使用することもできます。 –

+0

すぐにお返事ありがとうございます。明日これを試してみる。私がrejectAndDontRequeueを行う場合、これはDeadLetterQueueで終了しますか?メッセージが再配信された場合(少なくとも1回以上+おそらくより多く配信される)にこれを実行したいので、これを通常のACKとして扱いたいと思います。 Inbound-channel-adaterの内部でトランザクション属性がトランザクションで機能しない理由も知っていますか?アドバイスとして適用された場合は機能しますか? (質問の2番目の部分)。 –

+0

メッセージが再配信されても​​jdbcがすでにコミットされている場合、jdbcをロールバックする例外をスローしたいが、ウサギのメッセージを確認する(パイプラインの処理の最後にコミットと確認を行うため)。 –

関連する問題