バンド間相互作用。 開発者向けのEquinox

こんにちは! 繰り返しますが、チュートリアルとしての多くのコード。 ;)



OSGi環境では、バンドルの概念は基本です。 その目的からわかるように、システムのコンポーネントとしてのバンドルは、起動した瞬間から独自の生活を送り、サービス機能を実装できます。



この投稿では、バンドルが相互に通信する方法についてお話したいと思います。



たとえば、次のように定式化された簡単なタスクがあります。「workerbundleバンドルのバックグラウンドサービスは、20秒ごとに「preworkfunction」と呼ばれる処理を実行します。彼が「仕事関数」を実行するように。



しかし、それではなく、より簡単なものから始めましょう:起動時に登録し、シャットダウン時に登録から削除できるバンドルのレジストリを内部に保持する必要がある特定のRegistererバンドルがあります。



この問題を解決するには、バンドル間でイベントを交換するためのキューであるEventAdminサービスを使用します。 最初に、Registererバンドルのアクティベーターを記述します。これは、他のバンドルからメッセージを受け取ります。



メッセージ受信の実装



public class Activator implements BundleActivator { private Register mRegister; public void start(BundleContext context) throws Exception { mRegister = new Register(); /* *       . */ context.registerService(EventHandler.class.getName(), new ActivationEventHandler(mRegister), getHandlerServiceProperties( "ru/futurelink/app/web/usecase/Activator" )); /* *     */ Dictionary<String, Object> props = new Hashtable<String, Object>(); props.put("contextName", "app"); context.registerService(ApplicationConfiguration.class.getName(), new ApplicationConfig(mRegister), props ); } public void stop(BundleContext context) throws Exception {} protected Dictionary<String, Object> getHandlerServiceProperties(String... topics) { Dictionary<String, Object> result = new Hashtable<String, Object>(); result.put(EventConstants.EVENT_TOPIC, topics); return result; } }
      
      







ここでは、件名行「ru / futurelink / app / web / usecase / Activator」でメッセージを処理するサービスを登録します(この件名のメッセージをサブスクライブします)。 そのようなトピックを含むメッセージは、サブスクライブされているバンドルで受信できるという事実に注意する価値があります。 このようなレジストリだけでは何の利点もありません。この場合、さらにレジストリを使用する場所にRAPアプリケーションサービスに転送する必要があります。 したがって、コンストラクターにパラメーターを追加して、この投稿からApplicationConfigをオーバーライドします。



 public class ApplicationConfig implements ApplicationConfiguration { private Register mRegister; public ApplicationConfig(Register register) { mRegister = register; } }
      
      







Registerクラス自体は特別なものを表すものではなく、その実装は重要ではありません。 たとえば、その中には、登録済みのバンドル名のコレクションなどがあります。



ただし、これはレジストリレシーバーのメッセージハンドラです。



 public class ActivationEventHandler implements EventHandler { private Register mRegister; public UseCaseActivationEventHandler(Register register) { mRegister = register; } @Override public void handleEvent(Event event) { String bundle = (String) event.getProperty("bundleName"); Integer activated = (Integer) event.getProperty("activated"); BundleContext context = (BundleContext)event.getProperty("bundleContext"); if (activated == 1) { mRegister.registerBundle(bundle, context); } else { mRegister.unregisterBundle(bundle); } } }
      
      







ここで処理が終了します。 上記のトピックを含むメッセージを受信すると、bundleNameパラメーターで名前が送信されたバンドルが登録されます。 有効化されたパラメータ== 1の場合、バンドルはレジストリに追加する必要があると見なされます。



メッセージ送信の実装



開始と停止に関するメッセージを送信するバンドルアクティベータを作成しましょう。



 public class ClientActivator implements BundleActivator { private ServiceTracker mServiceTracker; private EventAdmin mEventAdmin; private Logger mLogger; private String mBundleName; public ClientActivator() {} public void addUsecase(UseCaseInfo info) { mBundleName = info.getBundleName(); } @Override public void start(BundleContext context) throws Exception { mServiceTracker = new ServiceTracker( context, EventAdmin.class.getName(), null); mServiceTracker.open(); mEventAdmin = (EventAdmin) mServiceTracker.getService(); postActivationEvent(context); } @Override public void stop(BundleContext context) throws Exception { postDeactivationEvent(context); } private void postActivationEvent(BundleContext context) { if (mEventAdmin != null) { //     Dictionary<String, Object> props = new Hashtable<String, Object>(); props.put("bundleName", mBundleName); props.put("bundleContext", context); props.put("activated", 1); mEventAdmin.postEvent( new Event("ru/futurelink/app/web/usecase/Activator", props)); } else { mLogger.error("Cannot get to EventAdmin service!"); } } private void postDeactivationEvent(BundleContext context) { if (mEventAdmin != null) { Dictionary<String, Object> props = new Hashtable<String, Object>(); props.put("bundleName", mBundleName); props.put("activated", 0); mEventAdmin.postEvent( new Event("ru/futurelink/app/web/usecase/Activator", props)); mServiceTracker.close(); } else { System.out.println("Cannot get to EventAdmin service!"); } } protected Dictionary<String, Object> getHandlerServiceProperties(String... topics) { Dictionary<String, Object> result = new Hashtable<String, Object>(); result.put(EventConstants.EVENT_TOPIC, topics); return result; } }
      
      







ここで何が起こっていますか? バンドルがアクティブ化されると、システムで自然に起動されるはずのEventAdminサービスオブジェクトが取得されます。 実行されていない場合、mEventAdmin == null。 さらに、タスクのロジックについて-バンドルの開始と停止に関するメッセージを送信します。



なぜ私と一緒に使用されるのですか? バンドルを停止した後、その中に実装されているモジュールの機能を即座に無効にしてアクセスできないようにします。 エラー、言い訳はありません-サイトの一部をオフにして、ユーザーがこの部分を使用しようとしたときに現在利用できないことをユーザーに通知するだけです。 また、このバンドルに関連する機能を無効にします。 メインアプリケーションは、モジュールの状態を認識している必要がありますが、モジュールに依存することはできません。この場合、イベントを通じて通知する内容のみを認識しています。



ところで、バンドルのコンテキストもメッセージで送信されることに注意する必要があります。



上記のことを考えると、仲間と通信し、EventAdminを通じて彼の状態を知らせることができるバックグラウンドサービスの実装は、すでに些細な作業です。



トピックに関する質問や追加をお願いします...;)



All Articles