Osgi 在启动捆绑包之前要求服务处于活动状态
我已经编写了一个BundleActivator,它应该在bundle启动之前更新某些配置。我需要ConfigurationAdmin服务,但我从BundleActivator的start方法中的BundleContext中获得了一个空ServiceReference BundleActivator扩展了以下抽象类,只实现了特定的更新逻辑:Osgi 在启动捆绑包之前要求服务处于活动状态,osgi,Osgi,我已经编写了一个BundleActivator,它应该在bundle启动之前更新某些配置。我需要ConfigurationAdmin服务,但我从BundleActivator的start方法中的BundleContext中获得了一个空ServiceReference BundleActivator扩展了以下抽象类,只实现了特定的更新逻辑: public abstract class AbstractConfigUpdater implements BundleActivator { p
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);
}
}
清单头已经生成,但我仍然得到一个空ServiceReference。我该如何解决这个问题?或者,在启动配置的组件之前,我是否可以采取其他方法来更新配置?我不知道这是否有帮助,但您可以开发一个
org.osgi.service.cm.ConfigurationPlugin
来截取运行时注入的所有属性并对其进行修改:
public class MyConfigurationPlugin implements BundleActivator, ConfigurationPlugin {
ServiceRegistration<ConfigurationPlugin> configPluginRef;
@Override
public void start(BundleContext context) throws Exception {
//... init the config plugin
Map<String,String> properties = new HashMap<>();
configPluginRef = context.registerService(
ConfigurationPlugin.class,
this,
new Hashtable<>(properties));
}
@Override
public void modifyConfiguration(ServiceReference<?> reference,
Dictionary<String, Object> properties) {
/*
* View and possibly modify a set of configuration properties
* before they are sent to the Managed Service or the Managed Service Factory.
*/
}
}
公共类MyConfigurationPlugin实现BundleActivator、ConfigurationPlugin{
服务注册configPluginRef;
@凌驾
public void start(BundleContext)引发异常{
//…初始化配置插件
映射属性=新的HashMap();
configPluginRef=context.registerService(
ConfigurationPlugin.class,
这
新的哈希表(属性);
}
@凌驾
公共无效修改配置(ServiceReference,
字典属性){
/*
*查看并可能修改一组配置属性
*在将它们发送到托管服务或托管服务工厂之前。
*/
}
}
当然,声明式服务方法是一种简单得多的选择:
@Component (
service= {},
configurationPid={
configPid1,
configPid2,
...
})
public class MyComponent {
@Activate
public void activate(BundleContext context, Map<String, String> properties) {
}
@Modified
public void updated(BundleContext context, Map<String, String> properties) {
// Called when properties change
}
}
@组件(
服务={},
组态PID={
配置PID1,
配置PID2,
...
})
公共类MyComponent{
@激活
公共void激活(BundleContext、地图属性){
}
@修改
已更新公共void(BundleContext、地图属性){
//属性更改时调用
}
}
但是在这种情况下,您不能更改属性值:您只能对属性更改做出反应。您可以使用OSGi等待并从服务注册表检索服务
比如说,
import org.osgi.framework.Constants
import org.osgi.framework.Filter;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.service.cm.ConfigurationAdmin;
...
private static final long TIMEOUT_MILLIS = 10000;
@Override
public void start(final BundleContext context) throws Exception {
Filter filter = context.createFilter("(" + Constants.OBJECTCLASS + "=org.osgi.service.cm.ConfigurationAdmin)");
ServiceTracker<?, ?> configurationAdminTracker = new ServiceTracker<>(context, filter, null);
configurationAdminTracker.open();
ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) configurationAdminTracker.waitForService(TIMEOUT_MILLIS);
configurationAdminTracker.close();
if (configurationAdmin == null) {
// Not found
}
...
}
import org.osgi.framework.Constants
导入org.osgi.framework.Filter;
导入org.osgi.util.tracker.ServiceTracker;
导入org.osgi.service.cm.ConfigurationAdmin;
...
专用静态最终长超时\u毫秒=10000;
@凌驾
public void start(final BundleContext)引发异常{
Filter Filter=context.createFilter(“+Constants.OBJECTCLASS+”=org.osgi.service.cm.ConfigurationAdmin)”;
ServiceTracker configurationAdminTracker=新ServiceTracker(上下文、筛选器、空);
configurationAdminTracker.open();
ConfigurationAdmin ConfigurationAdmin=(ConfigurationAdmin)configurationAdminTracker.waitForService(超时\u毫秒);
configurationAdminTracker.close();
if(configurationAdmin==null){
//找不到
}
...
}
是否有任何理由不使用声明性服务(DS)?您试图解决的问题在Activator中确实很难解决,但在DS中却微不足道。您还将静态依赖项(需要功能)与动态依赖项(此捆绑包应处于活动状态)混淆。它们是两个不同的东西,不相关。Require功能可确保安装了捆绑包,但不能保证服务已注册,因为这可能取决于其他事项。感谢您对Require功能的说明。我之所以选择BundleActivator而不是DS组件,是因为我想在bundle启动时更新配置,因为配置的ObjectClassDefinition已经更改,我想在激活相应的DS组件之前运行配置更新。你看过R7中的OSGi配置器了吗?(或其在v2archive.osgi.enroute/osgi.enroute.configurator.simple.provider中的前身)。这可能会以更简单的方式解决您的问题。你现在要走的路是一个兔子洞。
import org.osgi.framework.Constants
import org.osgi.framework.Filter;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.service.cm.ConfigurationAdmin;
...
private static final long TIMEOUT_MILLIS = 10000;
@Override
public void start(final BundleContext context) throws Exception {
Filter filter = context.createFilter("(" + Constants.OBJECTCLASS + "=org.osgi.service.cm.ConfigurationAdmin)");
ServiceTracker<?, ?> configurationAdminTracker = new ServiceTracker<>(context, filter, null);
configurationAdminTracker.open();
ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) configurationAdminTracker.waitForService(TIMEOUT_MILLIS);
configurationAdminTracker.close();
if (configurationAdmin == null) {
// Not found
}
...
}