嵌入式Neo4j 2.1.6无法在OSGi环境中启动

时间:2015-02-01 23:29:44

标签: neo4j osgi apache-servicemix

我们使用Apache ServiceMix 5.3.0运行模块化应用程序平台。我需要使用持久性服务扩展我们的系统 - 所以我想构建一个包含Neo4J 2.1.6的OSGi包。

在我的pom.xml(Maven)中我使用maven-bundle-plugin(org.apache.felix)来构建捆绑包。我已将neo4j-kernelneo4j-lucene-index个库中的几乎所有包添加到<Export-Package>部分。

部署后,我的捆绑包显示在&#34;已解决&#34;州。但是,当它开始时它会抛出这个:

org.osgi.framework.BundleException: Activator start error ...
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
at org.neo4j.graphdb.factory.GraphDatabaseSettings.<clinit (GraphDatabaseSettings.java:69)

我的激活码如下所示(异常发生在最后一个命令):

  GraphDatabaseFactory factory = new GraphDatabaseFactory();
/*      
  ArrayList<CacheProvider> caches = new ArrayList();
  caches.add(new SoftCacheProvider());
  factory.setCacheProviders(caches);
*/      
  GraphDatabaseBuilder builder = factory.newEmbeddedDatabaseBuilder("neo4j-db");
  graphDb = builder.newGraphDatabase();

(如果评论的部分是否有效,则没有任何区别。)

错误模式与this question中的错误模式类似。

我怀疑来自org.neo4j.graphdb.factory.GraphDatabaseSettings(第259f行)的以下方法中的恶魔无法找到任何CacheProvider个实例,尽管它们在我的包中被打包并引用(org.neo4j.kernel.impl.cache...):

 private static String[] availableCaches()
 {
    List<String> available = new ArrayList<>();
    for ( CacheProvider cacheProvider : Service.load( CacheProvider.class ) )
    {
        available.add( cacheProvider.getName() );
    }
 ...
    return available.toArray( new String[available.size()] );
 }

我认为这是一个OSGi类加载器问题,而不是Neo4J问题。任何想法如何在这里继续?

1 个答案:

答案 0 :(得分:1)

我设法同时解决了我的问题。正如Neil所说,它既不是OSGi问题,也不是Neo4J错误。相反,我必须学习更多关于Neo4J如何绑定其扩展以及如何相应地塑造OSGi依赖关系以获得成功的课程。

这些是我昨天研究的结果:

(1)收集所有包

我的错误是依靠maven-bundle-plugin的能力来解析项目并自动将所有内部依赖关系分解为包级别(这是OSGi所必需的)。这适用于由import语句声明的类关系,但是,当然,在使用反射方法绑定外部内容时会失败。

由于应用程序在我的JUnit环境中运行良好,我的问题的原因必须包括OSGi环境中缺少的资源。

解决方案是虔诚地列出插件Export-PackagePrivate-PackageImport-Package部分中每个库的每个单独的包(列表相当长),而不是信任通配符。

(2)Neo4J内核扩展

听从上述话题,我摆脱了上面提到的ArrayIndexOutOfBoundsException,但我遇到了其他(类似的)异常。在我了解了Neo4J的“内核扩展”概念后,我获得了成功。

Neo4J(我有2.1.6版本)引入了“内核扩展”来连接可交换模块,以便在运行时进行缓存和索引。为了应用某个扩展,只需要将相应的jar添加到类路径中。每个库在META-INF/services下携带一个或多个描述符文件,告诉可用的实现。这些文件由内核查找和处理,以便查找和绑定其扩展(索引和缓存的扩展是必需的)。

在我安全地将所有必要的java软件包包含在我的bundly之后,只有META-INF/services中的描述符文件丢失了。 This code向我展示了如何将这些资源添加到捆绑包中(在<Embed-Dependency>中搜索maven-bundle-plugin部分。

Neo4J libs还包含一个蓝图描述符,用于自动将主要类作为服务发布(例如GraphDatabaseFactory)。这些资源位于OSGI-INF/blueprint/下,也应包含在捆绑包中。

我的Neo4J OSGi包的最终pom.xml如下所示:

 <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>my.group</groupId>
    <artifactId>neo4jBundle</artifactId>
    <version>0.1.0</version>
    <packaging>bundle</packaging>

    <properties>
      <neo4j-version>2.1.6</neo4j-version>
      <lucene-version>3.6.2</lucene-version>
    </properties>

    <dependencies>
      <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-kernel</artifactId>
        <version>${neo4j-version}</version>
      </dependency>
      <dependency>
        <groupId>org.neo4j</groupId>
        <artifactId>neo4j-lucene-index</artifactId>
        <version>${neo4j-version}</version>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-nop</artifactId>
      </dependency>
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.1.2</version>
      </dependency>
    </dependencies>

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.felix</groupId>
          <artifactId>maven-bundle-plugin</artifactId>
          <extensions>true</extensions>
          <configuration>
            <instructions>
              <Bundle-Name>org.neo4j.kernel</Bundle-Name>
              <Export-Package>org.neo4j.graphdb.*;version=${neo4j-version},
              ... {all neo4j packages} ...
                org.apache.lucene;version=${lucene-version},
              ... {all lucene packages} ...
                org.slf4j.impl
              </Export-Package>
              <Private-Package>
                javax.transaction,
                javax.transaction.xa,
                ch.qos.logback.classic,
                ... {all logback.classic packages} ...
                ch.qos.logback.core,
                ... {all logback.core packages} ...              
                org.slf4j.*
              </Private-Package>
              <Import-Package>
                javax.lang.model,
                ... {some javax packages to be imported from the runtime} ...
                !sun.misc,
                ... {exclude uneccessary packages to limit dependency} ...
                *
              </Import-Package>
              <Embed-Dependency>
                *;groupId=org.neo4j;artifactId=neo4j-kernel;inline=META-INF/services/*,
                *;groupId=org.neo4j;artifactId=neo4j-kernel;inline=OSGI-INF/blueprint/*,
                *;groupId=org.neo4j;artifactId=neo4j-lucene-index;inline=META-INF/services/*,              
                *;groupId=org.neo4j;artifactId=neo4j-lucene-index;inline=OSGI-INF/blueprint/*              
              </Embed-Dependency>
            </instructions>
          </configuration>
        </plugin>
      </plugins>
    </build>
  </project>

备注:这是一个纯库包,没有任何其他代码。我使用Activator的应用程序位于一个单独的包中。 这个例子只显示我解决问题的方法。我的例子并没有声称可以生成通用的Neo4J软件包。根据您想要的功能以及运行时已部署的东西的社会,您可能需要添加或省略某些包以使一切​​正常工作。