java - 未调用 OSGi 修改事件方法

标签 java osgi apache-felix equinox declarative-services

我正在使用 OSGi DS 组件和 ConfigurationAdmin。

我创建了一个简单的可配置组件

@Component(service=ConfigurableService.class)
public class ConfigurableService {

  private String message;

  @Activate
  public void activate(Map<String, Object> params) {
    System.out.println("Activate configurable");
    message = (String) params.get("msg");
  }

  @Modified
  public void modified(Map<String, Object> params) {
    System.out.println("Modify configurable");
    message = (String) params.get("msg");
  }

  @Deactivate
  public void deactivate(Map<String, Object> params) {
    System.out.println("Deactivate configurable");
    message = (String) params.get("msg");
  }

  public void execute() {
    System.out.println("Service says: " + message);
  }
}

然后我创建了一个 Felix Gogo shell 命令组件来通过 ConfigurationAdmin 触发配置

@Component(property =   {
    CommandProcessor.COMMAND_SCOPE + "=fipro",
    CommandProcessor.COMMAND_FUNCTION + "=configure"
},
service = ConfigurationCommand.class
)
public class ConfigurationCommand {

  private ConfigurationAdmin cm;

  @Reference(unbind="-")
  public void setConfigAdmin(ConfigurationAdmin cm) {
    this.cm = cm;
  }

  public void configure(String input) throws IOException {
    Configuration config = cm.getConfiguration("org.fipro.osgi.config.ConfigurableService");
    Hashtable<String, Object> props = new Hashtable<>();
    props.put("msg", input);
    config.update(props);
  }
}

最后我创建了另一个 Felix Gogo shell 命令组件,它使用 ConfigurableService

@Component(property =   {
    CommandProcessor.COMMAND_SCOPE + "=fipro",
    CommandProcessor.COMMAND_FUNCTION + "=welcome"
},
service = WelcomeCommand.class
)
public class WelcomeCommand {

  private ConfigurableService service;

  @Reference(unbind="-")
  public void setConfigurable(ConfigurableService service) {
    this.service = service;
  }

  public void updatedConfigurable(ConfigurableService service, Map<String, Object> properties) {
    System.out.println("ConfigurableService updated");
  }

  public void welcome() {
    service.execute();
  }
}

如果我使用包含这些组件的 bundle 启动 OSGi 应用程序,我希望在执行 welcome 时最初,我将看到该组件已激活并且服务输出为空,因为尚未应用任何配置(确保这会在连续调用时发生变化)。如果我之后执行 configure Dirk我期望用@Modified注释的方法执行后表明服务配置已更新。我还期望updatedConfigurable WelcomeCommand中的方法被执行。至少这是我阅读规范后的理解。

现在我观察到 Equinox 和 Felix 的不同行为。

春分:

修改后的方法按预期调用,ConfigurableService配置正确。但是updatedConfigurable(<Service>, <Map>)不被调用。仅当我更改方法签名以采用 ServiceReference 时更新后的方法被调用。

规范规定所有引用事件方法都支持以下方法签名

void <method-name>(ServiceReference);
void <method-name>(<parameter-type>);
void <method-name>(<parameter-type>, Map);

我在规范中没有看到更新的方法是否有异常(exception),或者这是 Equinox 中的一个问题,我应该为此提出问题?

菲利克斯:

如果我在 Bndtools 中的 Felix 上运行相同的示例,则修改后的方法和更新方法都不会被调用。我检查了ConfigurationCommand并且有可用的 ConfigurationAdmin,因此更新配置也不异常(exception)。但它从未以某种方式得到应用。

在 Felix 上运行示例时我是否遗漏了某些内容?

更新:

将控制台输出添加到每个生命周期事件方法会创建以下输出:

____________________________
Welcome to Apache Felix Gogo

g! ConfigurationCommand: Activate
ConfigurableService: Activate
WelcomeCommand: Activate
welcome
Service says: null
g! configure Dirk
g! welcome
Service says: null
g! exit 0
WelcomeCommand: Deactivate
ConfigurableService: Deactivate
ConfigurationCommand: Deactivate

如您所见,修改和更新事件永远不会被调用。

最佳答案

我认为问题在于 Gogo 命令的生命周期。

当命令未运行时,Gogo 不会保留服务对象。它跟踪 ServiceReference,但在您实际调用 welcome 命令之前不会调用 getService。因此,当您调用 welcome 时,WelcomeCommand 组件将被实例化,这会强制同时实例化 ConfigurableService

稍后,当welcome命令完成时,WelcomeCommand被释放,因此WelcomeCommandConfigurableService都将被释放GC 检测。因此,ConfigurableService 的任何实例都不会存在足够长的时间来接收 Modified 事件。

要解决此问题,请尝试使 WelcomeCommand 立即:

@Component(immediate = true, ...)

更新

通过电子邮件与 Dirk 进一步讨论后发现问题出在位置绑定(bind)。在配置管理中,配置默认“绑定(bind)”到创建它们的 bundle ,在本例中是包含 ConfigurationCommand 的 bundle 。一旦绑定(bind),它们就不能被另一个包使用,因此 ConfigurableService 永远不会看到配置。

要创建可由任何 bundle 使用的未绑定(bind)配置,请调用 ConfigAdmin.getConfiguration() 的双参数版本,并为第二个参数传递 null

关于java - 未调用 OSGi 修改事件方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36932825/

相关文章:

osgi - 使用 Context Loader 加载资源失败并出现 NullPointerException

osgi - 如何在 Apache Felix maven-bundle-plugin 中设置 Provide-Capability header ?

java - 是否可以获取具有 WebElement 的 By 对象

仿函数上的 Java8 热点

java - 管理大型 OSGi 应用程序

java - 关于使用 OSGi 设置 Maven 多模块项目的反馈

java - Collections.sort 对 java 对象列表进行排序

Java Swing TitledBorder 自定义颜色

java - 无法从 dev.eclipse.org cvs 导入项目

java - Apache FELIX JAX-RS 更改上下文路径