MBassador
を用いてイベントのハンドリングを行っている場合、デフォルトではハンドラ内部で例外が発生しても何事も無かったようになってしまい、エラーが発生したことすら分からないような状態になってしまいます。
さすがにこれはまずいので、基本的にはエラーをハンドリングをするためのエラーハンドラをEventBusに対してセットする必要があります。
エラーハンドラをセットしない場合
まず、エラーハンドラをセットしなかった場合の動きを確認しておきます
■Handlerの定義
ハンドラ内であえてIllegalArgumentException
をスローするようにしています
import net.engio.mbassy.listener.Handler; public class MsgHandler { @Handler public void handlMessage(String msg){ System.out.println("handle start. msg=" + msg); System.out.println("---------------"); throw new IllegalArgumentException("null parameter"); } }
■EventBusを作成してメッセージ送信
EventBusに上で定義したハンドラをセットしてメッセージを送信しています。
import net.engio.mbassy.bus.MBassador; public static void main(String[] args) { MBassador<Object> bus = new MBassador<>(); bus.subscribe(new MsgHandler()); bus.publishAsync("msg-1"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("\n>>> App end"); }
■実行結果
handle start. msg=msg-1 --------------- >>> App end
エラー(IllegalArgumentException
)が発生したことが全く分からない状態になっています
エラーハンドラをセットする場合
次にEventBusに対してエラーハンドラをセットするサンプルです。
(メッセージのHandlerには先の例と同じMsgHandler
クラスを使います)
■エラーハンドラの定義
エラーハンドラはIPublicationErrorHandler
インターフェースを実装したクラスとして定義する必要があります
(EventBus内での例外発生時に、handleError
メソッドにエラーの詳細情報が渡されて呼び出されます。)
import net.engio.mbassy.bus.error.IPublicationErrorHandler; import net.engio.mbassy.bus.error.PublicationError; final class EventBusErrorHandler implements IPublicationErrorHandler { @Override public void handleError(PublicationError publicationError) { System.out.println("publicationError = " + publicationError); publicationError.getCause().printStackTrace(); } }
■EventBusを作成してメッセージ送信
EventBusに上で定義したハンドラをセットしてメッセージを送信しています。
先の例とは違いIBusConfiguration
を生成してIBusConfiguration#addPublicationErrorHandler
でエラーハンドラをセットします。
そして生成したIBusConfiguration
をEventBus(MBassador
のコンストラクタ)に渡します。
import net.engio.mbassy.bus.MBassador; import net.engio.mbassy.bus.config.BusConfiguration; import net.engio.mbassy.bus.config.Feature; import net.engio.mbassy.bus.config.IBusConfiguration; public static void main(String[] args) { IBusConfiguration config = new BusConfiguration() .addFeature(Feature.SyncPubSub.Default()) .addFeature(Feature.AsynchronousHandlerInvocation.Default()) .addFeature(Feature.AsynchronousMessageDispatch.Default()) .addPublicationErrorHandler(new EventBusErrorHandler()); MBassador<Object> bus = new MBassador<>(config); bus.subscribe(new MsgHandler()); bus.publishAsync("msg-1"); try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("\n>>> App end"); }
■実行結果
handle start. msg=msg-1 --------------- publicationError = PublicationError{ cause=java.lang.reflect.InvocationTargetException message='Error during invocation of message handler. There might be an access rights problem. Do you use non public inner classes?' handler=public void trial.app.mbassador.ErrorMsgHandler.handlMessage(java.lang.String) listener=trial.app.mbassador.ErrorMsgHandler@68de145 publishedMessage=msg-1} java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at net.engio.mbassy.dispatch.ReflectiveHandlerInvocation.invoke(ReflectiveHandlerInvocation.java:29) at net.engio.mbassy.dispatch.MessageDispatcher.dispatch(MessageDispatcher.java:30) at net.engio.mbassy.dispatch.FilteredMessageDispatcher.dispatch(FilteredMessageDispatcher.java:42) at net.engio.mbassy.subscription.Subscription.publish(Subscription.java:72) at net.engio.mbassy.bus.MessagePublication.execute(MessagePublication.java:49) at net.engio.mbassy.bus.AbstractSyncAsyncMessageBus$1.run(AbstractSyncAsyncMessageBus.java:67) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.IllegalArgumentException: null parameter at trial.app.mbassador.ErrorMsgHandler.handlMessage(ErrorMsgHandler.java:13) ... 11 more >>> App end
メッセージのハンドラ内で例外がスローされた際に、エラーハンドラが動作していることが分かります。
エラー発生時の原因例外はPublicationError#getCause
から辿ることができます。