在服务启动时禁用OSGi服务的正确方法是什么?

时间:2009-10-14 14:09:58

标签: java osgi declarative-services

我创建了一个带有暴露(声明)服务的OSGi包。如果我,当调用激活时,注意到某些东西是不对的,这样我就无法提供服务,我需要防止它暴露。目前激活功能如下:

public void activate(ComponentContext context, Map<String, Object> properties) {
    pid = (String) properties.get(Constants.SERVICE_PID);
    try {
       ...
    }
    catch(Exception e) {
        context.disableComponent(pid);
    }
}

另一个替代方法就是像这样包装/传播异常(或者抛出一个新异常):

public void activate(ComponentContext context, Map<String, Object> properties) {
    try {
       ...
    }
    catch(Exception e) {
        throw new ComponentException("Some reason");
    }
}

我找不到OSGi Service Platform Service Compendium中声明性服务部分中指定的正确行为,但我可能遗漏了某些内容

2 个答案:

答案 0 :(得分:9)

嗯,对我来说,如果发生错误,应该抛出异常似乎是合乎逻辑的。基本上,你正在做的是在start方法中模仿BundleActivator的行为。当start方法返回而没有Exception时,bundle进入ACTIVE状态(否则它保持在RESOLVED状态)。我在DS规范中找到了一个有点合适的段落(我强调了有趣的部分):

  

组件实例必须先完成激活才能取消激活。一旦组件配置被停用或由于异常而无法激活,SCR必须取消绑定所有组件的绑定服务并丢弃对与激活相关联的组件实例的所有引用。

OSGi 4.2 cmpn spec

中的第112.5.6节P.320

我同意这不是很清楚,所以如果你想保持安全(更安全而不是遗憾),我会建议做组合(规范允许)。

public void activate(ComponentContext context, Map<String, Object> properties) {
    try {
       ...
    } catch(Exception e) {
        context.disableComponent((String) properties.get(Constants.SERVICE_PID));
        // not sure if a CE is best here... Maybe just rethrow the original one
        throw new ComponentException("Some reason");
    }
}

干杯, 米尔科

答案 1 :(得分:1)

禁用自身的组件不太可能是适当的OSGI设计。当情况好转时,什么会启用组件?启用/禁用状态旨在与激活/停用的逻辑级别不同。

正确设计的OSGI代码应正确处理激活失败时抛出ComponentException(或其他异常)的代码。假设组件注册了一个服务,服务引用将可用,但尝试获取服务将返回null。 DS将正确处理对服务的引用,并且任何直接尝试从服务引用获取服务的代码都必须正确处理服务实际不可用的可能性。

然而,这可能令人困惑。在Felix DS中,我实现了一个扩展,组件可以更改自己的服务属性,尽管这已经被规范所接受。使用此扩展,组件可以在激活或修改成功时添加服务属性(如active = true),并在修改失败或取消激活时将其删除。该服务的客户端可以过滤此服务属性,例如(活性=真)。

相关问题