【问题标题】:Non static reference is giving NPE in OsgiCommandSupport for custom commands非静态参考在 OsgiCommandSupport 中为自定义命令提供 NPE
【发布时间】:2016-01-07 08:20:06
【问题描述】:

我正在尝试在 Apache karaf 版本 2.3.10 中实现自定义命令。

@Component
@Command (scope = "test", name = "list", description = "list all the test commands")
public class CustomCommand extends OsgiCommandSupport
{
...
    @Reference (bind = "bindMethod", unbind = "unbindMethod", cardinality = ReferenceCardinality.MANDATORY_UNARY, policy = ReferencePolicy.DYNAMIC)
    private SampleService mySampleService;
    ...

     protected void bindMethod(SampleService aSampleService)
    {
        mySampleService = aSampleService;
    }

    protected void unbindMethod(Services aSampleService)
    {
        mySampleService = null;
    }
     @Override
    protected Object doExecute() throws Exception
    {
        mySampleService.printCommands(); // nullpointer exception is thrown for non static sampleservice reference
        System.out.println("Command printed test:")
    }
}

安装捆绑包后,我得到了用于非静态 sampleservice 参考的 NPE。 在 bindServices 中,引用已正确解析。如果我将 Sampleservice 更改为静态,那么一切正常。 这背后的原因是什么?

【问题讨论】:

    标签: java osgi apache-karaf osgi-bundle


    【解决方案1】:

    原因可能是为 CustomCommand 类创建了两个实例。一个是 felix scr 创建的,另一个可能是 blueprint 创建的。

    如果您使用静态引用,则 scr 完成的注入对所有实例都是可见的。静态变量不是一个好的解决方案,因为如果 scr 注入太晚,仍然存在时间问题。

    Karaf 命令不是单例。对于命令的每次调用,都会创建一个新的 CustomCommand 实例。所以使用 DS 创建命令通常是行不通的。

    【讨论】:

    • 谢谢克里斯蒂安。我没有使用蓝图。您能否提供有关 scr 注入中的时序问题的参考或描述。有什么办法可以避免静电?
    • 克里斯蒂安 我不相信这是对的。为什么你不能使用 DS 创建命令?这只是一项服务……诚然,我不是 Karaf 用户,但我一直使用 DS 创建简单的 Gogo 命令。我觉得这其实是@Reference声明搞砸的问题,看bind方法名。它也不应该是动态引用。
    • 在普通的 gogo 中很容易,因为命令是单例的。不幸的是,卡拉夫使用了不同的模型。用户实现的类不是真正的命令,它是一个动作。然后,Karaf 为对该命令的每次调用实例化一个对象。见github.com/apache/karaf/blob/karaf-2.3.x/shell/console/src/main/…
    • 所以Karaf 不支持普通的Gogo 命令? Gogo 的一个有趣行为是每次调用命令时它都会从 ServiceReference 获取服务,然后释放它。因此,对于默认的延迟 DS 组件,您确实会看到它上下弹跳。您可以通过设置 immediate=true 来修改它。
    • 据我所知,karaf 支持普通的 gogo 命令,但许多 karaf 功能随后不起作用。喜欢帮助和完成。 Guillaume 开始致力于提供更好的支持,但目前还没有完成。我试图让 karaf 团队切换到 karaf 4 的 gogo 模型,但没有成功。
    【解决方案2】:

    您的@Reference 声明声明绑定方法名为bindMethod,但您的类中没有这样的方法。相反,您将其称为bindServices。同样unbind方法名也不正确。

    也不需要使用动态引用策略。

    【讨论】:

    • 对不起,这是我的错误。它的拼写错误。正如我对静态参考所说的那样,它工作得很好。也许我会检查静态策略。
    • 好的,那么它可能是动态策略。有一个竞态条件...因为你指定了动态,服务引用可以在组件激活后注入。
    • 你也不需要 unbind 方法。
    • 为什么不呢?你试过了吗?会发生什么?
    • 我已将 policy = ReferencePolicy.DYNAMIC 更改为 policy = ReferencePolicy.STATIC。并且没有静态引用(私有 SampleService mySampleService)。它仍然给了 NPE
    猜你喜欢
    • 2021-09-14
    • 2011-06-08
    • 2016-01-21
    • 2013-11-14
    • 1970-01-01
    • 2020-12-30
    • 2021-01-16
    • 1970-01-01
    • 2011-07-13
    相关资源
    最近更新 更多