java - 带有组件 XML 文件的 OSGI DeclarativeService Multiton

标签 java osgi

我需要给定 OSGI 组件的多实例,即一些 bundle 将获得相同的实现实例,而其他 bundle 需要另一个实例。如果可能,我需要使用 XML 文件 而不是注释(如 @Component)。我使用的是混合 OSGI 4.3 平台,包含来自 eclipse 和 felix 的 bundle 。

比方说,我的服务界面是这样的:

public interface SocketService {

    // Does nothing if already listening on given port
    public void startListening(int port);

    public String getNextMessage();
}

声明性 XML 文件如下所示并且工作正常:

<?xml version="1.0" encoding="UTF-8"?>
  <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="SocketService">
    <implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
    <service>
      <provide interface="declarativemultiton.service.SocketService"/>
    </service>
</scr:component>

这些是消费者类,具有相同的语义:

public class Consumer1 {

    public void activate() {
        System.out.println("Consumer1 activated");
    }

    public void setSocketService(SocketService service) {
        System.out.println("Consumer1 got SocketService@" + System.identityHashCode(service));
    }
}

public class Consumer2 {

    public void activate() {
        System.out.println("Consumer2 activated");
    }

    public void setSocketService(SocketService service) {
        System.out.println("Consumer2 got socketservice@" + System.identityHashCode(service));
    }
}

以及它们的组件定义 XML:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer1" immediate="true">
   <implementation class="declarativemultiton.consumer1.Consumer1"/>
   <reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Consumer2" immediate="true">
   <implementation class="declarativemultiton.consumer2.Consumer2"/>
   <reference bind="setSocketService" cardinality="1..1" interface="declarativemultiton.service.SocketService" name="SocketService" policy="static"/>
</scr:component>

一切都按预期工作,并且两个组件都获得相同的实例:

Socket Service Impl activated
Consumer1 got SocketService@1769618707
Consumer1 activated
Consumer2 got socketservice@1769618707
Consumer2 activated

我需要 Component1 和 Component2 获取不同 SocketService 实例,并且 Component2 和 Component3(未显示)具有相同 SocketService 实例。

如果我将配置策略更改为“要求”,则不会激活消费者组件:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="require" name="SocketService">
   <implementation class="declarativemultiton.service.impl.SocketServiceImpl"/>
   <service>
      <provide interface="declarativemultiton.service.SocketService"/>
   </service>
</scr:component>    

这是我迷路的地方,我不知道如何将配置动态传递给 SocketService。在阅读有关 ConfigurationAdmin、ManagedService、ManagedServiceFactory、ComponentFactory 等内容时,我一直在纠结。我找不到一个具体、简洁的解决方案。有一些相互矛盾的方法,比如这个答案 https://stackoverflow.com/a/4129464/330464说不要使用 ManagedService,而是使用 Karaf 教程 http://sully6768.blogspot.com.tr/2012/09/declarative-services-with-karaf-part-4.html解决了它的使用问题。

最佳答案

我认为您使用服务属性来识别或区分使用组件上的 SocketFactory 实例和目标属性以确定使用哪一个是正确的方法,但我建议使用配置而不是每个实现使用多个组件 xml类(class)。我不太清楚您有多少个 SocketFactory 或消费者的实现类。为了说明,我将假设每个人都有一个。

您可以通过 config admin 使用 DS 组件的配置,而不是复制组件 xml 并在那里修改属性。 Peter Kriens 在此处对 DS 包括配置进行了很好的解释: http://enroute.osgi.org/services/org.osgi.service.component.html .以下是一些更详细地涵盖使用配置设置引用的步骤:

  1. 将配置 pid 添加到您的组件 xml。让我们假设 socketFactory 为 socketFactory,消费者为 consumer。

  2. 安装配置管理员。我觉得 felix 和 eclipse 都很好,我只用过 felix。

  3. 在您想要安排套接字工厂启动的包中,执行一些获取 ConfigAdmin 实例的代码并调用类似

    Configuration sfc = ca.createFactoryConfiguration("socketFactory", null);
    Hashtable<String, Object> props = new Hashtable<String, Object>();
    props.put("socketType", "MyType");
    sfc.update(props);
    

如果此代码与 SocketFactory 代码捆绑在一起,您可以省略 null 参数。 这将生成一个带有 socketType=MyType 服务属性的 SocketFactory 组件,类似于您对组件属性所做的操作。

  1. 在要安排消费者设置的 bundle 中,执行类似的操作但使用目标过滤器:

    Configuration cc = ca.createFactoryConfiguration("consumer", null);
    Hashtable<String, Object> props = new Hashtable<String, Object>();
    props.put("SocketService.target", "(socketType=MyType)");
    cc.update(props);
    

这将生成具有指定目标过滤器的消费者组件。

您也许可以选择使用例如felix fileinstall 从属性文件安装配置。这是非常声明性的,但我没有任何经验,而且我看到有些人很难将所有部分排成一行,因此它可以工作。在工作中,我有幸使用了一个基于 xml 的系统:它从元类型生成一个模式,并将 xml 配置文档(符合生成的模式)与元类型结合以生成配置。它可以从例如生成目标过滤器元素。嵌套的 xml。我经常希望有一个开源版本。

顺便说一句,您可能想重新审视您对 spec ds 注释的回避。它们不在运行时使用,而是在您组装包时由 bnd 处理。 (您正在使用 bnd,不是吗?)。 Bnd 将为与您的组件兼容的尽可能低的 ds 版本生成 component.xml,并且它会比您手动执行更多的验证(至少比我手动执行的要多)。

关于java - 带有组件 XML 文件的 OSGI DeclarativeService Multiton,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33171587/

相关文章:

java - 配置 OSGI Enroute REST 应用程序以允许异步请求

java - 如何从 JBoss AS 7 上的(可能是远程的)Web 应用程序访问 OSGi 服务?

java - LoggerFactory无法获取Logger

java - Servlet-Applet 通信

java - 无法重新绘制屏幕,​​但无法清除以前的形状

java - 从索引属性中删除项目 - JavaBeans 问题

java - 通过不同属性引用同一个表的 Hibernate JOIN FETCH 导致 1+N 查询?

java - 通过 REST 将 XML 数组接收到 MULE ESB 流中

java - 将 Equinox 3.2.1 嵌入到 WebSphere 中

java - 启用 OSGi/RCP 插件从另一个非依赖插件加载类