2016-06-23 6 views
1

@TransactionalEventListenerを使用してイベントをリッスンしようとしていますが、トランザクションが終了する前でもイベントが聴取されます。メソッドが例外をスローした場合でも、イベントはリッスンされます。ここでSpring @TransactionalEventListenerが期待どおりに動作しない

は私がこのシナリオでは

@Component 
public class SampleListener{ 

    @TransactionalEventListener 
    public void handleSomeTransactionalEvent(SampleEvent event){ 
     //Some Logic 
    } 
} 

@Service 
@Transactional 
public class SampleInsertService{ 

    @Autowired 
    private ApplicationEventPublisher applicationEventPublisher; 

    public void someTransactionalMethod(SomeDTO someDTO){ 
      //Delete all call 

      //Again Insert all calls 

      //Publish event after insert 
      applicationEventPublisher.publishEvent(new SampleEvent(this, String.EventType, someDTO)); 

      /** Some other call to DB which throws exception **/ 
    } 

} 


public class SampleEvent implements ApplicationEvent{ 

    private String eventType; 

    public SampleEvent(Object source, String eventType, SampleDTO sampleDTO){ 
      //some logic 
    } 

} 

を行うにしようとしています何のサンプルコードで、私のリスナーは、すぐにインサートが、私の取引方法で完了すると呼ばなっています。私はこれがすべてのDBコールが終了し、コミットが完了した後に呼び出されるべきだと思います。私は何かが欠けている。私はSpring 4.3.0を使用しています。これについて私を案内してください。

答えて

1

私は問題を把握しました。この問題は、Spring MVCを使用していない場合は発生しません。この問題は、rootapplicationcontextと子のwebapplicationcontext(Spring MVCの両方)にロードされたリスナークラスのために発生しました。

私はapplication-context.xmlとspring-web.xmlの両方で一般的なコンポーネントスキャンを行っていました。したがって、リスナークラスは2回読み込まれました。 application-context.xmlの場合はもう一度、spring-web.xmlの場合はもう一度。 spring-web.xmlの一般的なコンポーネントスキャンを削除し、spring-web.xmlのコントローラパッケージとフィルタパッケージのみを記述すると、問題は解決しました。

トランザクションイベントリスナーは、トランザクションのコミット後に1回だけ呼び出されました。

+0

私はロードされる1つのXML設定ファイルしか持っていません。しかし、私はあなたと同じ症状を見ています。コンポーネントが2回ロードされているかどうかを確認する最良の方法は何ですか? –

+0

@DavidWebb、私が説明したシナリオと同じようにlisternerクラスが2回ロードされていると思われる場合は、アプリケーションの起動時にSpringによって生成されたログで検証できるはずです。私はSpring Beanの初期化に関する情報を得るためにTRACEレベルをオンにしなければならないかもしれないと信じています。起動時にログ内で2回見つけた場合、それが問題になる可能性があります。お役に立てれば。 – tejaswini

1

TransactionalEventListenerは異なるTransactionPhaseでリッスンできます。アノテーションにはさまざまな段階を指定できます。あなたの場合AFTER_COMMITまたはAFTER_COMPLETIONが役に立ちます。

+0

@TransactionalEventListenerのデフォルトフェーズはAFTER_COMMITなので、私はフェーズについて言及していません。私はhandleSomeTransactionalEvent()は、すべてのDB呼び出しがServiceメソッドで終了した後に呼び出されるべきだと考えています。しかし、そうではありません。最後のDBコールが実行される前、DBにコミットされる前に呼び出されます。私が何かを逃しているかどうか私に知らせてください。 – tejaswini

関連する問題