簡體   English   中英

OSGI中的聲明式服務

[英]Declarative services in OSGI

我創建了一個(非常簡單的)測試來確定如何使用Apache Felix發送和接收事件。

這是我的發件人:

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 clean package創建它,然后將這個jar文件安裝到我的Apache felix容器中並啟動它。 但是,沒有任何反應。 一無所有。

提前致謝!

您似乎已到達那里! 如您所知,Event Admin使用白板模型來接收事件。 重要的是,您需要告訴白板您想聽哪些主題,做什么。

%%%更新%%%

事件管理主題名稱使用由/字符分隔的標記層次結構。 發布事件時,您可以針對特定主題進行發布,例如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;
}

這不是您訪問包的BundleContext的方式。 如果確實需要BundleContext ,則應將其作為參數注入到@Activate注釋的方法中。 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批注將服務屬性添加到您的組件,也可以使用Component Property批注從OSGi R7版本(幾個月后)中添加服務屬性。 在這種情況下,您需要這樣設置event.topics屬性:

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

然后,您可以根據需要完全擺脫Activate方法。

最后:

事件管理員不是消息隊列,發布者是一次性發送。 因此,如果發布者在未完全注冊處理程序之前發送事件,則它將永遠不會收到該事件。 考慮使發布者發送定期事件,或確保接收者發布者之前啟動以便您看到消息。

PS

從技術上講這不是問題,但是我看到您正在使用2.4版本的maven-bundle-plugin 這是非常舊的,當前發布的bnd版本是3.5.0。 Bnd團隊也已開始提供您可能想要查看的自己的Maven插件(例如bnd-maven-plugin )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM