【问题标题】:OSGI services strange behaviourOSGI 服务奇怪的行为
【发布时间】:2014-04-24 00:57:51
【问题描述】:

我正在经历我认为是来自 Osgi 服务及其跟踪的奇怪行为。

我有两个包:ProviderClient。 Provider 提供 Client 接收和使用的“comm service”。

一开始,客户端通过 OSGi TrackerService 检索服务,这要归功于 ClientActivator 类上的这个方法:

private CommService retrieveCommService(BundleContext bc) 
                              throws InterruptedException {

        //create the tracker
        ServiceTracker tracker = new ServiceTracker(bc, CommService.class.
                                                   getName(), null);
        tracker.open();

        //timeout of 5 seconds to find the service
        CommService service = (CommService) tracker.waitForService(5000);
        tracker.close();

        return service;
    }

这样,当Client 包的激活器被执行时,跟踪器就找到了服务。

如果 ServiceTracker 工作正常,这就是我在 OSGi 控制台上键入 services 时看到的内容:

{some.project.folder.imaComms.CommService}={service.id=46}
  Registered by bundle: MA_Provider [2062]
  Bundles using service:
    MA_Client [2565]

无论如何,在阅读了一些关于 OSGi 服务的文档后,我决定使用 DS 而不是 ServiceTrackers。

所以,我创建了组件(提供程序和客户端 xml 文件)并实现了绑定和取消绑定方法:

 public void setComms(CommService comm){        
        this.comm = comm;
        System.out.println("got comms!");
    }

    public void unsetComms(CommService comm){           
        this.comm=null;
        System.out.println("lost comms..");
    }

而且,这一次,当我在控制台上键入 services 时,我看到的是:

{some.project.folder.imaComms.CommService}={component.name=
 MA_Comm_Provider, component.id=18, service.id=47}
  Registered by bundle: MA_Provider [2062]
  Bundles using service:
        MA_Client [2565]

所以,每当我停止 Provider 捆绑包时,控制台上都会出现消息 lost comms...。当我再次启动它时,得到了通信!是消息。


到目前为止一切都很完美。但我想做最后一次测试。我实现了绑定和取消绑定方法,组件定义,但我也让 ServiceTrackerClientActivator 上找到服务。

结果有点奇怪。

当我启动 OSGi 框架时,got comms! 出现在控制台上,好像 DS 绑定方法正在工作并向我的Client 提供服务。但是,如果我输入 services,我得到的是这样的:

 {some.project.folder.imaComms.CommService}={service.id=46}
      Registered by bundle: MA_Provider [2062]
      Bundles using service:
        MA_Client [2565]


 {some.project.folder.imaComms.CommService}={component.name=
  MA_Comm_Provider, component.id=18, service.id=47}
      Registered by bundle: MA_Provider [2062]
      No Bundles using this service.

客户端正在通过 ServiceTracker 使用服务。如果我停止 ProviderService,我会从 unbind 方法收到这条消息:*lost comms...*

如果我再次启动捆绑包会发生什么?是的,“收到消息!”出现在控制台上...但话又说回来,如果我查看服务,service id 47(DS 服务)没有被任何人使用。 什么? O_o

有什么线索吗?提前致谢!

另外,忘了提一下:每当我重新启动 Provider 捆绑包时,Osgi 启动捆绑包大约需要 2-3 分钟,它会完全停止任何其他捆绑包的工作。


28/03/14 更新

提供者和客户端 DS 的 XML 文件

提供者

  <?xml version="1.0" encoding="UTF-8"?>
    <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"  name="MA_Comms_Provider">
       <implementation class="some.project.folder.maComms.CommServiceImpl"/>
       <service>
          <provide interface="some.project.folder.imaComms.CommService"/>
       </service>
    </scr:component>

客户

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="MA_Comms_consumer">
   <implementation class="some.project.folder.maClient.MyClientImpl"/>
   <reference bind="setComms" cardinality="1..1" interface="some.project.folder.imaComms.CommService" name="CommService" policy="static" unbind="unsetComms"/>
</scr:component>

提供者和客户端的清单文件

提供者

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: MA_Provider
Bundle-SymbolicName: MA_Provider
Bundle-Version: 1.0.0
Bundle-ClassPath: src/,
 .
Bundle-Activator: myActivator
Export-Package: ...
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: ...,
 org.osgi.framework;version="1.5.0",
 org.osgi.util.tracker;version="1.4.2"
Service-Component: OSGI-INF/CommsProvider.xml

客户

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: MaClient
Bundle-SymbolicName: MA_Client
Bundle-Version: 1.0.0
Bundle-ClassPath: src/,
 .
Bundle-Activator: ...
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Import-Package: ...,
 org.osgi.framework;version="1.3.0",
 org.osgi.util.tracker;version="1.4.2"
Export-Package: es.techabout.meetabout.macomms
Service-Component: OSGI-INF/CommsConsumer.xml, ...

应该注意的是,我省略了文件夹、类和服务的真实名称,所以即使我的文本在类、文件夹的名称方面有任何错误……我向您保证真实项目的构建没有错误任何。

【问题讨论】:

  • 你使用的是哪个 Osgi 实现?
  • 春分。忘了说,对不起
  • 您是否在提供者捆绑激活器中同时拥有通信服务的 DS 声明服务注册?这会导致同一个服务被注册两次。
  • 是的,我有它:“但我想做最后一次测试。我实现了绑定和取消绑定方法,组件定义,但我也让 ServiceTracker 在 ClientActivator 上找到服务”。问题是,它被注册了两次,并且 bind 和 unbind 方法都在工作......即使你,似乎也没有人使用 DS 服务!

标签: java service osgi equinox osgi-bundle


【解决方案1】:

我不明白你的问题。您的 DS 版本似乎工作正常,所以您决定弄乱它,然后它就不再工作了?也许回到原来的工作。

service.id=46 似乎是您的提供程序捆绑包的“原始”服务注册。 service.id=47 是 DS 代表您的提供商捆绑包进行的注册。请参阅 component.name 服务属性。因此,您拥有注册 2 个服务的提供程序包。

您没有显示客户端捆绑包的组件描述,因此我们可以假设这两种服务都可以,因此选择两者之一。

最后,你原来对ServiceTracker的使用是错误的。在您使用该服务时,跟踪器必须保持打开状态。当您使用跟踪器时,您永远不会将服务对象直接保存在长期变量中。您将跟踪器保存在长期变量中,并在每次需要服务时咨询服务对象。否则,您假设一旦获得服务对象,它就永远有效。

【讨论】:

  • 它工作正常。我没有弄乱任何东西,我只是在做一些测试。正如我在问题中解释的那样,我知道服务 46 和 47 做什么。如果你认为我的主要问题是 osgi 服务不再工作,你应该再读一遍。我的问题不是“它不工作”,而是“为什么它会那样工作”:似乎服务 47 从未被使用过,但是我声明的 DS 服务的 bind 和 unbind 方法(如果没有在跟踪器中注册服务,它们被声明为可以正常工作)实际上正在工作,因为它们使用和丢弃服务。
  • 您的客户端捆绑包可以使用任一服务(46 或 47)。客户不关心谁注册了服务。只有服务符合选择标准。跟踪器也不注册服务。它是关于使用服务的。
【解决方案2】:

所以如果我理解正确的话,你已经安装了以下捆绑包:

  1. 使用 DS 的提供商
  2. 提供者直接注册服务
  3. 使用 DS 的客户端
  4. 使用 ServiceTracker 的客户端

如果您启动所有这些捆绑包,您会看到 DS 客户端找到了提供者服务之一。您还可以看到,如果您停止提供该服务的捆绑包,DS 客户端不会找到其他 Provider 服务。这听起来可能很奇怪,但如果您设法划分了班级空间,就可以解释这一点。对于一个明确的答案,我们需要所有 4 个捆绑包的清单,但我的猜测是 DS 客户端连接到其中一个提供程序的导出,而另一个提供程序具有不同的导出。

可以解释您没有看到使用 ServiceTracker 的客户端出现的事实,因为您在代码中打开和关闭了该跟踪器。关闭后,OSGi 不再将服务视为“正在使用”。是的,您仍然保留参考,但您不知道该服务是否仍然存在。

所以让我们看看清单(也许还有 DS XML),这样我们就可以看看我的理论是否正确。

【讨论】:

  • 嗯或多或少,但我只有两个捆绑包:Provider 和 Client。 Provider 直接注册服务(使用 ServiceTracker),同时有一个 manifest 通过 DS 注册服务。客户端同时使用 ServiceTracker 和 DS。希望它有助于使事情更清楚,很抱歉造成误解。
  • 好的,所以一个提供者注册了两个服务,当它停止时,两个服务都消失了。这也解释了为什么客户端只找到一个服务,而当两个服务都消失时,它又没有了。不过,提供实际的 XML 和捆绑清单作为问题的一部分会有所帮助(正如我之前所说,我现在有点“猜测”,因为有些事情我们不知道)。
  • 首先,Marcel,感谢您抽出宝贵时间。我想明确指出这是一个“为什么这样做”的问题,而不是我正在努力解决的真正问题(因为代码确实可以完美运行)。我为这两个包添加了 XML 文件和清单。再次感谢您的宝贵时间。
猜你喜欢
  • 2013-02-03
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
  • 2016-12-18
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多