9

我创建了一个带有公开(声明性)服务的 OSGi 包。如果我在调用 activate 时注意到有什么不对劲以至于我无法提供服务,我需要防止它被暴露。目前激活函数如下所示:

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 服务平台服务纲要中的声明性服务部分中找不到指定的正确行为,但我可能遗漏了一些东西

4

2 回答 2

9

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

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

OSGi 4.2 cmpn 规范中的第 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");
    }
}

干杯,米尔科

于 2009-10-15T16:06:23.833 回答
1

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

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

但是,这可能会令人困惑。在 Felix DS 中,我实现了一个扩展,组件可以更改它们自己的服务属性,尽管这还没有被规范接受。使用此扩展,组件可以在激活或修改成功时添加诸如 active=true 之类的服务属性,并在修改失败或停用时将其删除。服务的客户端可以过滤此服务属性,例如 (active=true)。

于 2017-04-10T17:52:45.643 回答