2016-06-22 4 views
1

私はGuava EventBusを同期して使用しています。いずれかのサブスクライバがExceptionをスローすると、どのようにトランザクション全体をロールバックできますか? EventBus加入者が捕捉しないExceptionをどのように投げることができますか?Guava EventBusサブスクライバから例外をスローする

+0

Iに例外を設定するには、クラスにラップする必要があり、それをスローするクラスにラップする必要がありますこれらのいずれかが可能であれば、驚くべきことです。 –

+0

これらが不可能な場合、これはイベントバスの制限ではありませんが、トランザクションでは使用できません。 – Shikhar

+0

はい。もちろん。 –

答えて

0

私は、出版社とサブスクライバ間で変数java.lang.ThreadLocalを使用して解決しました。

Publisherは、ローカル例外をスレッド読み込み、

public void publish(Event event) { 
    eventBus.post(event); 
    if(threadLocalException != null) { 
    Store threadLocalException in some variable say e 
    Clear threadLocalException variable 
    throw e; 
    } 
} 

加入者は、スレッドローカル変数

public abstract class EventSubscriber<T extends Event> { 

    @Subscribe 
    public void invoke(T event) { 
    try { 
     handle(event); 
    } catch (Exception e) { 
     Set thread local variable to e 
    } 
    } 

    protected abstract void handle(T event); 

} 
1

GuavaのEventBusクラスのソースコードを見るだけでいいです。

端から始めるのをしてみましょう:

にはどうすればEventBus加入者によってキャッチされることはありません例外を投げることができますか?

com.google.common.eventbus.Dispatcher#dispatchメソッドによって、加入者のメソッドが次々に呼び出されます。あなたのサブスクライバのメソッドを呼び出すために、EventBusはリフレクションのメソッドMethod#invokeを使用し、呼び出されたメソッドが例外をスローするとInvocationTargetExceptionをスローします。

次のように扱われますが、また、(あなたのExceptionに巻き付けされる)InvocationTargetException、見ることができるように:

} catch (InvocationTargetException e) { 
    if (e.getCause() instanceof Error) { 
    throw (Error) e.getCause(); 
    } 
    throw e; 
} 

上位レベルで、例外はそのように処理されます。

try { 
    invokeSubscriberMethod(event); 
} catch (InvocationTargetException e) { 
    bus.handleSubscriberException(e.getCause(), context(event)); 
} 

TL; DR

したがって、EventBus例外ハンドラを省略する唯一の方法Exceptionではなく、Errorをあなたの購読方法で投げることです。これは確かに悪い習慣です。

サブスクライバのいずれかが例外をスローすると、完全なトランザクションをどのようにロールバックできますか?

EventBus例外ハンドラは、com.google.common.eventbus.EventBus#handleSubscriberExceptionメソッドを呼び出すことによって例外を処理します。

try { 
    exceptionHandler.handleException(e, context); 
} catch (Throwable e2) { 
    // logging 
} 

例外ハンドラからスローされた例外は役に立ちません。

  • または手動では、このフロー内の任意の場所からロールバック専用としてトランザクションを設定する(それがすっごく悪いです)ご加入方法から

    1. どちらのスローエラー:あなたは2つの選択肢があります。私はそのようなもののための最良の場所は明らかにEventBus例外ハンドラだと思う。
  • 0

    EventBusを継承し、例外をスローする独自のeventBusを作成します。 パッケージはcom.google.common.eventbusでなければなりません。handleSubscriberExceptionは内部メソッドです。

    package com.google.common.eventbus; 
    
    import com.google.common.util.concurrent.MoreExecutors; 
    
    /** 
    * A eventbus wihch will throw exceptions during event handle process. 
    * @author ytm 
    * 
    */ 
    public class ErrorThrowEventBus extends EventBus { 
    
        /** 
        * Creates a new EventBus with the given {@code identifier}. 
        * 
        * @param identifier a brief name for this bus, for logging purposes. Should be a valid Java 
        *  identifier. 
        */ 
        public ErrorThrowEventBus(String identifier) { 
         super(
          identifier, 
          MoreExecutors.directExecutor(), 
          Dispatcher.perThreadDispatchQueue(), 
          LoggingHandler.INSTANCE); 
        } 
    
        /** 
        * Creates a new EventBus with the given {@link SubscriberExceptionHandler}. 
        * 
        * @param exceptionHandler Handler for subscriber exceptions. 
        * @since 16.0 
        */ 
        public ErrorThrowEventBus(SubscriberExceptionHandler exceptionHandler) { 
         super(
          "default", 
          MoreExecutors.directExecutor(), 
          Dispatcher.perThreadDispatchQueue(), 
          exceptionHandler); 
        } 
    
        /** 
        * Just throw a EventHandleException if there's any exception. 
        * @param e 
        * @param context 
        * @throws EventHandleException 
        */ 
        @Override 
        void handleSubscriberException(Throwable e, SubscriberExceptionContext context) throws EventHandleException { 
         throw new EventHandleException(e); 
        } 
    } 
    
    関連する問題