2017-12-06 23 views
1

Apache Felixを使用してイベントを送受信する方法を決定する(非常に)簡単なテストを作成しました。OSGIの宣言的サービス

これは私の送信者である:

package be.pxl; 

import org.osgi.service.component.annotations.Activate; 
import org.osgi.service.component.annotations.Component; 
import org.osgi.service.component.annotations.Reference; 
import org.osgi.service.event.Event; 
import org.osgi.service.event.EventAdmin; 

import java.util.HashMap; 

@Component(name = "be.pxl.Publisher", immediate = true) 
public class Publisher { 

    EventAdmin admin; 

    @Activate 
    public void run(Object object) { 
     System.out.println("IN PUBLISHER"); 
     Event event = new Event("event", new HashMap<String, Object>()); 
     System.out.println("\tEVENT: " + event); 
     admin.postEvent(event); 
     System.out.println("\tADMIN: " + admin); 
    } 

    @Reference(name="be.pxl.admin", service = EventAdmin.class) 
    protected void setEventAdmin(EventAdmin admin) { 
     this.admin = admin; 
    } 

} 

これは私の受信機である:

package be.pxl; 

import org.osgi.framework.BundleContext; 
import org.osgi.service.component.annotations.Activate; 
import org.osgi.service.component.annotations.Component; 
import org.osgi.service.component.annotations.Reference; 
import org.osgi.service.event.Event; 
import org.osgi.service.event.EventConstants; 
import org.osgi.service.event.EventHandler; 
import java.util.Dictionary; 
import java.util.Hashtable; 

@Component(name = "be.pxl.Subscriber", immediate = true) 
public class Subscriber implements EventHandler { 

    private BundleContext context; 

    @Activate 
    public void run(Object object) { 
     System.out.println("IN SUBSCRIBER"); 
     System.out.println("\tIN RUN METHOD"); 
     String[] topics = new String[]{"event"}; 
     Dictionary props = new Hashtable(); 
     props.put(EventConstants.EVENT_TOPIC, topics); 
     System.out.println("\t\tCONTEXT: " + context); 
     context.registerService(EventHandler.class.getName(), this, props); 
     System.out.println("\t\tCONTEXT AFTER REGISTERSERVICE: " + context); 
    } 

    public void handleEvent(Event event) { 
     System.out.println("IN SUBSCRIBER"); 
     String text = event.getProperty("text").toString(); 
     System.out.println("\tEVENT CALLED: " + text); 
    } 

    @Reference(name="be.pxl.context", service=BundleContext.class) 
    protected void setBundleContex(BundleContext context) { 
     this.context = context; 
    } 

} 

これは私の送信者のPOMです:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>be.pxl</groupId> 
    <artifactId>EventSender</artifactId> 
    <version>1.0-SNAPSHOT</version> 

    <dependencies> 
     <dependency> 
      <groupId>org.osgi</groupId> 
      <artifactId>org.osgi.service.event</artifactId> 
      <version>1.3.1</version> 
      <scope>provided</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.osgi</groupId> 
      <artifactId>org.osgi.core</artifactId> 
      <version>6.0.0</version> 
      <scope>provided</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.osgi</groupId> 
      <artifactId>org.osgi.service.component.annotations</artifactId> 
      <version>1.3.0</version> 
      <scope>provided</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.eclipse.osgi</groupId> 
      <artifactId>org.eclipse.osgi.services</artifactId> 
      <version>3.2.100.v20100503</version> 
     </dependency> 

    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.felix</groupId> 
       <artifactId>maven-bundle-plugin</artifactId> 
       <version>2.4.0</version> 
       <extensions>true</extensions> 
       <configuration> 
        <instructions> 
         <Bundle-Vendor>SmartCampus</Bundle-Vendor> 
         <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> 
         <Export-Package> 
          be.pxl.*;version="1.0.0" 
         </Export-Package> 
         <Import-Package> 
          org.osgi.service.component.annotations 
          org.eclipse.osgi.service 
          org.osgi.core 
          org.osgi.service.event 
         </Import-Package> 
         <_dsannotations>*</_dsannotations> 
        </instructions> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 

</project> 

すべてが正常にコンパイル。私はmvnのクリーンなパッケージを使用してそれを作成し、私はこのjarファイルを私のApacheのfelixコンテナにインストールして起動します。しかし、何も起こらない。何もpritnsを得ることはありません。

ありがとうございます!

答えて

0

あなたはその道の大部分を占めているようです。特定したとおり、イベント管理者はホワイトボードモデルを使用してイベントを受信します。重要なのは、ホワイトボードにどのトピックを聞きたいのかを伝える必要があることです。

%%% %%%更新

イベント管理トピック名は、/文字で区切られたトークンの階層を使用しています。イベントを公開するときは、特定のトピック(例:foo/bar/baz)に公開します。イベントを受け取ると、登録された興味に合致するトピックに対してEventHandlerが呼び出されます。これらの関心事は、特定のトピックのためのものでも、ワイルドカードの一致を示すために*で終わるものもあります。たとえば、foo/bar/*は、foo/bar/bazに送信されたイベントを受信し、イベントはfoo/bar/fizzbuzzに送信されます。まず

は%%%戻る

%%%元にあなたのコードに問題のカップルは、しかし、があります

@Reference(name="be.pxl.context", service=BundleContext.class) 
protected void setBundleContex(BundleContext context) { 
    this.context = context; 
} 

これは、あなたがアクセスする方法ではありませんあなたのバンドルのBundleContextBundleContextが必要な場合は、注釈付きメソッドにパラメータとして注入する必要があります。 A BundleContextは決してサービスとして登録されるべきではありません(OSGiフレームワークへのあなたのバンドルの私的アクセスを表しています)。この参考文献があなたの例では不満であることがわかりました。あなたが実際に必要としないBundleContextしかし第二に

...理由:

@Activate 
public void run(Object object) { 
    System.out.println("IN SUBSCRIBER"); 
    System.out.println("\tIN RUN METHOD"); 
    String[] topics = new String[]{"event"}; 
    Dictionary props = new Hashtable(); 
    props.put(EventConstants.EVENT_TOPIC, topics); 
    System.out.println("\t\tCONTEXT: " + context); 
    context.registerService(EventHandler.class.getName(), this, props); 
    System.out.println("\t\tCONTEXT AFTER REGISTERSERVICE: " + context); 
} 

これは、Activateメソッドを書くための正しい方法ではありません(その結果、それが呼び出されていることはできません)、ここでサービスとしてコンポーネントを登録する必要はありません。クラスを@Componentにすると、直接実装された各インターフェイスを使用して自動的にサービスとして登録されます。これは、次のことを意味します。

@Component(name = "be.pxl.Subscriber", immediate = true) 
public class Subscriber implements EventHandler { 
    ... 
} 

は既にOSGi EventHandlerサービスです。

@Component注釈を使用してコンポーネントにサービスプロパティを追加したり、コンポーネントプロパティ注釈を使用してOSGi R7リリース(数ヶ月のために)からサービスプロパティを追加できます。この場合、あなたはこのようなあなたのevent.topicsプロパティを設定したい:あなたが好きな場合は、その後、完全にactivateメソッドを取り除くことができます

@Component(property="event.topics=event") 

。最後に

イベント管理者は、メッセージキューではなく、あなたの出版社がワンショット送信です。したがって、ハンドラが完全に登録される前にパブリッシャがイベントを送信すると、イベントは受信されません。発行者に定期的なイベントを送信させるか、受信者がメッセージを表示するようにより前にを開始することを確認してください。

P.S.

これは技術的に問題はありませんが、maven-bundle-pluginのバージョン2.4を使用していることがわかりました。これは非常にであり、現在リリースされているバージョンのbndは3.5.0です。また、Bndチームはあなたが見たいかもしれない独自のMavenプラグイン(bnd-maven-pluginなど)の提供を開始しました。

+0

この非常に参考になった説明をありがとう!しかし、コンポーネントアノテーションで宣言しているプロパティを使用するにはどうすればよいですか?また、コンポーネントの起動にBundleActivatorが必要ですか?このデモの目的は、すぐにサブスクライバを起動し、Apache Felixコンテナでパブリッシャを起動し、パブリッシャが送信したテキストを出力することです。 また、受信者がサイト運営者の前で開始することを確認するにはどうすればよいですか? ありがとうございます! –

+0

** @Componentで宣言しているプロパティを使用するにはどうすればいいですか?**答えにはすでに宣言方法が示されていますので、あなたの質問はイベント管理トピックに関するものと仮定します。私はこのためのセクションを追加しました。 ** BundleActivatorが必要ですか?**間違いなく。現代のOSGiアプリケーションで低レベルのAPIを使う理由はほとんどないので、人々はバンドルアクチベータを書かないことをお勧めします。 **出版社の前に受信機が始まっていることを確認するには?** gogoシェルがインストールされているなら、 'scr:list'コマンドと' scr:info'コマンドを使ってDSコンポーネントをチェックすることができます –

関連する問題