【发布时间】:2019-02-05 04:05:49
【问题描述】:
我编写了一个 BundleActivator,它应该在它的包启动之前更新某些配置。我需要 ConfigurationAdmin 服务,但我在 BundleActivator 的启动方法中从 BundleContext 获得了一个空的 ServiceReference。
BundleActivator扩展了以下抽象类,只实现了具体的更新逻辑:
public abstract class AbstractConfigUpdater implements BundleActivator {
private ServiceReference<ConfigurationAdmin> configurationAdminServiceReference;
@Override
public void start(final BundleContext context) throws Exception {
configurationAdminServiceReference = context.getServiceReference(ConfigurationAdmin.class);
final ConfigurationAdmin configurationAdmin = context.getService(configurationAdminServiceReference);
final Configuration[] configurations =
configurationAdmin.listConfigurations(getFilter());
if (configurations != null) {
for (final Configuration configuration : configurations) {
final Dictionary<String, Object> properties = configuration.getProperties();
if (updateProperties(properties)) {
configuration.update(properties);
}
}
}
}
protected abstract String getFilter();
/**
* Updates the properties if needed.
*
* @param properties
* the configuration properties
* @return if any modifications to the Dictionary were made
*/
protected abstract boolean updateProperties(final Dictionary<String, Object> properties);
@Override
public void stop(final BundleContext context) throws Exception {
context.ungetService(configurationAdminServiceReference);
}
}
我已经在具体的 BundleActivator 中添加了一个注释来生成一个清单头,以要求 ConfigurationAdmin 服务对包可用:
@RequireCapability(filter = "(objectClass=org.osgi.service.cm.ConfigurationAdmin)",
ns = "osgi.service",
resolution = Resolution.mandatory)
清单标头已生成,但我仍然得到一个空的 ServiceReference。我应该如何解决这个问题?或者是否有其他方法可以在启动组件之前更新配置?
【问题讨论】:
-
有什么理由不使用声明式服务 (DS)?您要解决的问题在 Activator 中非常困难,但在 DS 中微不足道。
-
您还将静态依赖项(Require-Capability)与动态依赖项(此捆绑包应该处于活动状态)混淆了。它们是两个不同的东西,不相关。 Require Capability 确保有一个捆绑包已安装,但不能保证该服务已注册,因为这可能取决于其他东西。
-
感谢您对 Require-Capability 的澄清。我选择 BundleActivator 而不是 DS 组件的原因是我想在 bundle 启动时更新配置,因为配置的 ObjectClassDefinition 已更改,我想在激活相应的 DS 组件之前运行配置更新。
-
您查看过 R7 中的 OSGi 配置器吗? (或其前身在 v2archive.osgi.enroute/osgi.enroute.configurator.simple.provider)。这可能会以更简单的方式解决您的问题。你现在的路是一个兔子洞。
标签: osgi