gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 08:02:27 25 4
gpt4 key购买 nike

我正在研究 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();
}
}

如果我使用包含这些组件的包启动 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 命令完成时,Welcommand 被释放,因此 WelcommandConfigurableService 都将被释放气相色谱。因此,ConfigurableService 的实例都无法存活足够长的时间来接收 Modified 事件。

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

@Component(immediate = true, ...)

更新

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

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

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com