在 OSGi 平台中使用 OpenStack4j

Use OpenStack4j in an OSGi platform

我想使用 OpenStack4j in an OSGi platform. Specifically I'm using Apache Karaf OSGi runtime (based on Apache Felix OSGi 实现)。

OpenStack4j 尝试发现连接器时出现问题。根据 Getting started 官方文档指南,我尝试使用此行实例化 v2.0 客户端:

OSClient os = OSFactory.builder()
                .endpoint("http://host:5000/v2.0")
                .credentials("user", "password")
                .tenantName("tenant")
                .authenticate();

我遇到了这个异常:

Caused by: java.lang.ExceptionInInitializerError
    at org.openstack4j.openstack.internal.OSAuthenticator.authenticateV2(OSAuthenticator.java:77)
    at org.openstack4j.openstack.internal.OSAuthenticator.invoke(OSAuthenticator.java:41)
    at org.openstack4j.openstack.client.OSClientBuilder$ClientV2.authenticate(OSClientBuilder.java:84)
    at org.openstack4j.openstack.client.OSClientBuilder$ClientV2.authenticate(OSClientBuilder.java:65)
    ... 19 more
Caused by: java.lang.NullPointerException
    at org.openstack4j.core.transport.internal.HttpExecutor.initService(HttpExecutor.java:32)
    at org.openstack4j.core.transport.internal.HttpExecutor.<init>(HttpExecutor.java:25)
    at org.openstack4j.core.transport.internal.HttpExecutor.<clinit>(HttpExecutor.java:20)
    ... 27 more

这似乎与连接器发现有关,但我不确定。

OpenStack4j不支持OSGi,I asked for it. I tried to solve the issue declaring a Apache Karaf feature, based on HTTPClient 4像这样:

<?xml version="1.0" encoding="UTF-8"?>
<features>

    <feature name="openstack4j" version="${openstack4j-version}">
        <feature version="${openstack4j-version}">openstack4j-httpclient</feature>

        <bundle dependency="true">mvn:com.google.guava/guava/17.0</bundle>

        <bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-databind/2.3.5</bundle>
        <bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-annotations/2.3.5</bundle>
        <bundle dependency="true">mvn:com.fasterxml.jackson.core/jackson-core/2.3.5</bundle>

        <bundle dependency="true">mvn:com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.3.5</bundle>
        <bundle dependency="true">mvn:org.yaml/snakeyaml/1.14</bundle>

        <bundle dependency="true">wrap:mvn:com.google.code.findbugs/jsr305/2.0.0</bundle>

        <bundle>wrap:mvn:org.pacesys/openstack4j-core/${openstack4j-version}</bundle>       
    </feature>

    <feature name="openstack4j-httpclient" version="${openstack4j-version}">
        <bundle dependency="true">wrap:mvn:commons-logging/commons-logging/${commons.logging.version}</bundle>

        <bundle dependency="true">wrap:mvn:org.apache.httpcomponents/httpclient/4.3.1</bundle>
        <bundle dependency="true">wrap:mvn:org.apache.httpcomponents/httpcore/4.3</bundle>

        <bundle>wrap:mvn:org.pacesys.openstack4j.connectors/openstack4j-httpclient/${openstack4j-version}</bundle>      
    </feature>

</features>

但是并没有解决我的问题

如何在我的 OSGi 环境中使用 OpenStack4j?

编辑: 我发现 NullPointerException 是由代码中的错误引起的(此处为 issue)。已修复。

无论如何,SPI 的问题仍然存在。

恐怕您的问题没有简单的解决方案。关于sources,HttpExecutor 正在通过ServiceLoader 寻找HttpExecutorService。这很可能不起作用,因为 ServiceLoader 对 BundleClassloader 一无所知,并且由于您从 Bundle 实例化它,所以很可能缺少所需的包导入。另一个原因可能是 ServiceLoader 使用父类加载器。

所以你有三种可能。
1) 确保您还在 bundle
中导入了 org.openstack4j.core.transport.internal 2) 将 TCCL (Thread Context ClassLoader) 设置为包含包的包的类加载器。所以 ServiceLoader 能够找到它。
3) 正如尼尔评论的那样,使用 Aries SPY Fly ...