首页 文章

OSGI服务奇怪的行为

提问于
浏览
2

我正在体验我认为Osgi服务及其跟踪的奇怪行为 .

我有两个捆绑包: ProviderClient . 提供商提供客户接收和使用的“通信服务” .

一开始,客户端通过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控制台上键入服务时看到的内容:

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

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

因此,我创建了组件(提供者和客户端xml文件)并实现了bind和unbind方法:

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..");
    }

而且,这一次,这是我在控制台上键入服务时看到的内容:

{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 包时,消息丢失了通信...出现在控制台上 . 当我再次启动它时,得到了通讯!是消息 .


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

结果有些奇怪 .

当我启动OSGi框架时,得到了通讯!出现在控制台上,好像 DS bind方法正在运行并将服务提供给我的 Client . 但如果我输入服务,这就是我得到的:

{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方法得到了这条消息:*丢失了通信... *

如果我再次启动捆绑包会发生什么?是的,“得到了通讯!”出现在控制台上......但是,如果我看一下服务,那么任何人都不会使用 service id 47 (DS服务) . 什么? O_O

有什么发生的线索?提前致谢!

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


更新28/03/14

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

Provider

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

Client

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

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

Provider

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

Client

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, ...

应该注意的是,我省略了文件夹,类和服务的真实名称,所以即使我的文本有关于类,文件夹名称的任何错误......,我向你保证真正的项目是在没有任何错误的情况下构建的 .

2 回答

  • 1

    因此,如果我理解正确,您已安装以下捆绑包:

    • 使用DS的提供商

    • 提供者直接注册服务

    • 使用DS的客户端

    • 使用ServiceTracker的客户端

    如果您启动所有这些捆绑包,您会看到DS客户端找到了一个提供商服务 . 您还会看到,如果停止提供该服务的捆绑包,则DS客户端将找不到其他提供者服务 . 这可能听起来很奇怪,但如果你设法对你的类空间进行分区,可以解释一下 . 关于这个问题的最终答案,我们是'd need all 4 bundle'的清单,但我的猜测是DS客户端连接到其中一个提供商的导出,而另一个提供商有不同的导出 .

    您可以解释因为您在代码中打开和关闭该跟踪器而无法看到使用ServiceTracker的客户端显示的事实 . 关闭后,OSGi不再将该服务视为“正在使用中” . 是的,您仍然保留参考,但您不知道该服务是否仍在那里 .

    因此,让我们看一下清单(也可能是DS XML),这样我们就能看出我的理论是否正确 .

  • 0

    我不明白你的问题 . 您的DS版本似乎工作正常,所以你决定搞乱它然后它不再工作?也许回到正在发挥作用的地方 .

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

    您没有显示客户端捆绑包的组件描述,因此我们可以假设它对任何一种服务都没问题,因此选择其中一种 .

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

相关问题