Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Osgi 在启动捆绑包之前要求服务处于活动状态_Osgi - Fatal编程技术网

Osgi 在启动捆绑包之前要求服务处于活动状态

Osgi 在启动捆绑包之前要求服务处于活动状态,osgi,Osgi,我已经编写了一个BundleActivator,它应该在bundle启动之前更新某些配置。我需要ConfigurationAdmin服务,但我从BundleActivator的start方法中的BundleContext中获得了一个空ServiceReference BundleActivator扩展了以下抽象类,只实现了特定的更新逻辑: public abstract class AbstractConfigUpdater implements BundleActivator { p

我已经编写了一个BundleActivator,它应该在bundle启动之前更新某些配置。我需要ConfigurationAdmin服务,但我从BundleActivator的start方法中的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);
    }

}

清单头已经生成,但我仍然得到一个空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
    }
    ...
}