如何在OSGi中实现ManagedServiceFactory? [英] How do you implement a ManagedServiceFactory in OSGi?

查看:65
本文介绍了如何在OSGi中实现ManagedServiceFactory?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试设置我自己的ManagedServiceFactory实现.这是我想做的事情:在每个配置的基础上,我需要某些服务的多个实例.使用DS,这些组件可以完美运行,但是现在我发现,这些服务应该根据自己的生命周期(即服务注册表中的(注销)注册)来处理自己的生命周期,具体取决于某些外部资源的可用性,而DS则无法实现.

Im currently trying to setup my own implementation of a ManagedServiceFactory. Here is what I'm trying to do: I need multiple instances of some service on a per-configuration base. With DS the components worked perfectly but now I found out that these services should handle there own lifecycle (i.e. (de)registration at the service registry) depending on the availability of some external resource, which is impossible with DS.

因此,我的想法是创建一个ManagedServiceFactory,然后从ConfigurationAdmin接收配置并创建我的类的实例.它们再次尝试在单独的线程中连接到资源,并在它们准备好运行时将自己注册为服务.

Thus my idea was to create a ManagedServiceFactory, which then would receive configs from the ConfigurationAdmin and create instances of my class. These again would try to connect to the resource in a seperate thread and register themselves as service when they're ready to operate.

由于我还没有实现这一点的运气,所以我试图将所有内容分解为最基本的部分,甚至没有处理动态(取消)注册,只是试图使ManagedServiceFacotry起作用:

Since I had no luck implementing this yet, I tried to break everything down to the most basic parts, not even dealing with the dynamic (de)registration, just trying to get the ManagedServiceFacotry to work:

package my.project.factory;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;

public class Factory implements BundleActivator, ManagedServiceFactory {

private ServiceRegistration myReg;
private BundleContext ctx;
private Map<String, ServiceRegistration> services;

@Override
public void start(BundleContext context) throws Exception {
    System.out.println("starting factory...");
    this.ctx = context;
    java.util.Dictionary properties = new Hashtable<String, Object>();
    properties.put(Constants.SERVICE_PID, "my.project.servicefactory");
    myReg = context.registerService(ManagedServiceFactory.class, this,
            properties);
    System.out.println("registered as ManagedServiceFactory");
    services = new HashMap<String, ServiceRegistration>();
}

@Override
public void stop(BundleContext context) throws Exception {
    for(ServiceRegistration reg : services.values()) {
        System.out.println("deregister " + reg);
        reg.unregister();
    }
    if(myReg != null) {
        myReg.unregister();
    } else {
        System.out.println("my service registration as already null " +
                           "(although it shouldn't)!");
    }
}

@Override
public String getName() {
    System.out.println("returning facotry name");
    return "ServiceFactory";
}

@Override
public void updated(String pid, Dictionary properties)
        throws ConfigurationException {
    System.out.println("retrieved update for pid " + pid);
    ServiceRegistration reg = services.get(pid);
    if (reg == null) {
        services.put(pid, ctx.registerService(ServiceInterface.class,
                new Service(), properties));
    } else {
        // i should do some update here
    }
}

@Override
public void deleted(String pid) {
    ServiceRegistration reg = services.get(pid);
    if (reg != null) {
        reg.unregister();
    }
}

}

现在,它应该从ConfigurationAdmin接收PID my.project.servicefactory的配置,不是吗? 但是它没有从ConfigurationAdmin接收任何配置.该捆绑包已启动,该服务已注册,并且在Web控制台中,我可以看到config admin拥有对ManagedServiceFactory的引用.是否有应设置的特定属性? 接口规范不建议这样做.实际上,我的实现与那里的示例大致相同.我不知道我在这里做错了什么,非常欢迎提供有关解决方案的指针.

Now, it should receive configurations from the ConfigurationAdmin for PID my.project.servicefactory, shouldn't it? But it does not receive any configurations from the ConfigurationAdmin. The bundle is started, the service is registered and in the web console, I can see the config admin holds a reference to my ManagedServiceFactory. Is there a certain property which should be set? The interface specification does not suggest that. Actually my implementation is more or less the same as the example there. I've no idea what I'm doing wrong here, any pointers to the solutions are very welcome.

此外,我原本以为可以将ManagedServiceFactory本身实现为DS,但这也是可能的,但同时我失败了:ConfigAdmin不会移交任何配置.

Also, I orginally thought to implement the ManagedServiceFactory itself as DS, which also should be possible, but I failed at the same point: no configurations are handed over by the ConfigAdmin.

更新 为了澄清这个问题:我认为这主要是一个配置问题.正如我所看到的,我应该能够为工厂指定两个PID,一个用于标识工厂本身的配置(如果有的话),另一个将通过该工厂提供服务,我认为应该是factory.pid .但是框架常量不包含这样的内容.

update To clarify the question: I think that this is mainly an configuration problem. As I see it, I should be able to specify two PIDs for the factory, one which identifies a configuration for the factory itself (if any), and one which would produce services trough this factory, which I thought should be the factory.pid. But the framework constants do not hold anything like this.

更新2 在搜索了一下Felix Fileinstall源代码后,我发现无论文件名中是否有-,它都会以不同的方式对待配置文件.将配置文件命名为my.project.servicefactory.cfg无效,但是按预期将名为my.project.servicefactory-foo.cfgmy.project.servicefactory-bar.cfg的配置正确地移交给了ManagedServiceFactory,并注册了带有ServiceInterface的多个服务.哇!

update 2 After searching a bit the Felix Fileinstall source code, I found out that it treats configuration files differently when there is a - in the filename or not. Having the configuration file named my.project.servicefactory.cfg it did not work, but the configs named my.project.servicefactory-foo.cfg and my.project.servicefactory-bar.cfg were properly handed over to my ManagedServiceFactory as expected, and multiple services with ServiceInterface were registered. Hurray!

更新3 如Neil所建议,我将声明式服务放入参与一个新问题以限制该问题的范围.

update 3 As proposed by Neil, I put the declarative service part in a new question to bound the scope of this one.

推荐答案

认为问题在于您拥有单例配置记录而不是工厂记录.您需要使用my.project.servicefactory作为 factoryPid createFactoryConfiguration方法调用Config Admin.

I think that the problem is you have a singleton configuration record rather than a factory record. You need to call Config Admin with the createFactoryConfiguration method using my.project.servicefactory as the factoryPid.

如果使用的是Apache Felix FileInstall(这是一种无需编写代码即可创建配置记录的简便方法),则需要在load目录中创建一个名为my.project.servicefactory-1.cfg的文件.您可以通过调用my.project.servicefactory-2.cfg等创建具有相同factoryPID的其他配置.

If you are using Apache Felix FileInstall (which is a nice easy way to create config records without writing code) then you need to create a file called my.project.servicefactory-1.cfg in the load directory. You can create further configurations with the same factoryPID by calling them my.project.servicefactory-2.cfg etc.

这篇关于如何在OSGi中实现ManagedServiceFactory?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆