Maven OSGI中的声明性服务

Maven OSGI中的声明性服务,maven,annotations,osgi,apache-felix,declarative-services,Maven,Annotations,Osgi,Apache Felix,Declarative Services,我创建了一个(非常)简单的测试来确定如何使用ApacheFelix发送和接收事件 这是我的发件人: 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.os

我创建了一个(非常)简单的测试来确定如何使用ApacheFelix发送和接收事件

这是我的发件人:

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;
    }

}
    <?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>
这是我的发件人的pom:

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;
    }

}
    <?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>

4.0.0
be.pxl
事件发送者
1.0-快照
org.osgi
org.osgi.service.event
1.3.1
假如
org.osgi
org.osgi.core
6.0.0
假如
org.osgi
org.osgi.service.component.annotations
1.3.0
假如
org.eclipse.osgi
org.eclipse.osgi.services
3.2.100.v20100503
org.apache.felix
maven捆绑插件
2.4.0
符合事实的
智能校园
${project.artifactId}
be.pxl.*;version=“1.0.0”
org.osgi.service.component.annotations
org.eclipse.osgi.service
org.osgi.core
org.osgi.service.event
*
一切都很好。我使用mvn clean包创建它,然后在ApacheFelix容器中安装这个jar文件并启动它。然而,什么也没有发生。没有什么能把pritns弄出来


提前谢谢

你似乎是最成功的!正如您所确定的,事件管理员使用白板模型来接收事件。重要的是,你需要告诉白板你想听哪些主题,你想做什么

%%%更新%%%

事件管理主题名称使用由
/
字符分隔的令牌层次结构。将事件发布到特定主题时,例如
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
永远不应该注册为服务(它代表您的bundle对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(name = "be.pxl.Subscriber", immediate = true)
public class Subscriber implements EventHandler {
    ...
}
已经是一个OSGi EventHandler服务

您可以使用
@component
注释将服务属性添加到组件中,也可以使用组件属性注释从OSGi R7版本(将在几个月后发布)中添加服务属性。在这种情况下,您需要设置
事件。主题
属性,如下所示:

@Component(property="event.topics=event")
然后,如果愿意,可以完全取消激活方法

最后:

事件管理不是消息队列,您的发布服务器是一次性发送。因此,如果您的发布服务器在处理程序完全注册之前发送事件,则它将永远不会接收该事件。考虑使发布者发送周期性事件,或者确保接收方在发布服务器之前启动,以便看到消息。 附言


这在技术上不是问题,但我看到您使用的是
maven bundle插件的2.4版。这是一个非常古老的版本,目前发布的bnd版本是3.5.0。Bnd团队也开始提供他们自己的Maven插件(例如
Bnd Maven插件
),您可能会想看看。

感谢您提供的非常有用的解释!但是如何使用我在组件注释中声明的属性呢?另外,我的组件启动时是否需要BundleActivator?本演示的目的是立即启动订阅服务器,然后在ApacheFelix容器中启动发布服务器,并打印出发布服务器发送的文本。此外,我如何确定接收器在发布者之前启动?提前谢谢!如何使用我用@Component声明的属性?答案已经显示了如何声明它,所以我假设您的问题是关于事件管理主题的。我为此添加了一个部分。我需要一个BundleActivator吗?绝对不是。我建议人们不要编写Bundle激活器,因为在现代OSGi应用程序中几乎没有理由使用低级API。我如何确定接收器在发布者之前启动?如果安装了gogo外壳,则可以使用
scr:list
scr:info
命令检查DS组件