如何在设置后直接使用引用的DS OSGi服务?

时间:2014-11-18 10:24:46

标签: java osgi

我几周前开始使用OSGi,对DS有疑问。

假设我有2个捆绑包,捆绑包A和捆绑包B.两者都通过DS / BND注释注册服务。

Bundle A引用了bundle B的服务,并实现了所需的set和unset函数。

@Reference(dynamic = true, optional = true)
    void setConnector(IDataBaseConnect connector) {
    this.connector = connector;
    doSomeStuff();
    sysout("Connector SET");  <---- NOT called when doSomeStuff runs into an error

}

当doSomeStuff()遇到错误

时,永远不会调用它
void unsetConnector(IDataBaseConnect connector){
   this.connector = null
}

正如你所看到的,我希望引用动态和可选,但是,如果连接器服务可用,我想在包A中做一些事情。

在我的案例中,Bundle B具有一些基本的数据库功能。 Bundle A使用它来从数据库中读取一些数据并将其缓存在一些java对象中。其他服务将使用此数据。

但是,我对这种方法有疑问。如果我的数据库服务引用设置为Bundle A,我在setConnector函数中启动我的数据库操作。只要一切顺利,我都没有问题。参考设置,数据变红,一切都很好。但是如果DB-Service遇到异常(是的,它被捕获并处理),DS似乎会忘记&#34;关于集合参考,当我停止服务时它永远不会被删除。

我想我不应该调用setConnector函数中的任何函数,但是如果是这样的话,我将如何实现一个仅在设置新引用时调用的方法?

2 个答案:

答案 0 :(得分:1)

在极少数情况下应使用动态和可选参考。到目前为止我既没有使用动态也没有可选参考,尽管我实现了很多组件。在数据库连接的情况下,还有其他问题:

  • 如果在运行两个SQL语句之间替换IDatabaseConnect引用怎么办?
  • 如果呼叫者访问了单独的功能,更换了IDatabaseConnect但全局事务是否相同怎么办?

我建议你应该使用非动态的非可选引用,并将 doSomeStuff()逻辑放入你的activate方法中。在这种情况下,您可以确保在业务逻辑运行时该引用可用。

答案 1 :(得分:1)

如果doSomeStuff()抛出异常然后从绑定方法setConnector传播出来,则DS将假定您的绑定方法已损坏,并且您的组件未能接受绑定服务。然后,DS会将服务视为未绑定到组件,因此不会调用该服务的unbind方法。

您需要在bind方法中处理来自doSomeStuff()的任何异常。例如:

@Reference(dynamic = true, optional = true)
void setConnector(IDataBaseConnect connector) {
  this.connector = connector;
  try {
    doSomeStuff();
  } catch (Exception e) {
     // handle e but don't let it propagate out of this bind method
  }
  sysout("Connector SET");
}