【问题标题】:Datanucleus, JDO and executable jar - how to do it?Datanucleus、JDO 和可执行 jar - 怎么做?
【发布时间】:2012-04-23 05:12:25
【问题描述】:

我正在使用 Datanucleus 和 JDO 为嵌入式 H2 数据库开发桌面应用程序。当我从 Eclipse 运行它时一切正常,但是当我尝试从中制作可执行 jar 时它停止工作。我收到以下错误:

org.datanucleus.exceptions.NucleusUserException:已指定持久化进程使用名称为“jdo”的 ClassLoaderResolver,但 DataNucleus 插件机制尚未发现此问题。请检查您的 CLASSPATH 和插件规范。

当然这表明我没有正确配置一些东西——我错过了什么?如果我遗漏了一些大的东西,它根本就不起作用,所以我假设它是一个有缺陷的可执行 jar。我在其他应用程序(例如 JPOX)中看到了该错误,该错误已得到修复,但没有给出任何解决方案。

整个错误堆栈跟踪:

Exception in thread "main" javax.jdo.JDOFatalInternalException: Unexpected exception caught.
        at javax.jdo.JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(JDOHelper.java:1193)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:808)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:701)
        at db.PersistenceManagerFilter.init(PersistenceManagerFilter.java:44)
        at Main.main(Main.java:26)
NestedThrowablesStackTrace:
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at javax.jdo.JDOHelper$16.run(JDOHelper.java:1965)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.jdo.JDOHelper.invoke(JDOHelper.java:1960)
        at javax.jdo.JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(JDOHelper.java:1166)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:808)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:701)
        at db.PersistenceManagerFilter.init(PersistenceManagerFilter.java:44)
        at Main.main(Main.java:26)
Caused by: org.datanucleus.exceptions.NucleusUserException: Persistence process has been specified to use a ClassLoaderResolver of name "jdo" yet this has not been found by the DataNucleus plugin mechanism. Please check your CLASSPATH and plugin specification.
        at org.datanucleus.NucleusContext.<init>(NucleusContext.java:233)
        at org.datanucleus.NucleusContext.<init>(NucleusContext.java:196)
        at org.datanucleus.NucleusContext.<init>(NucleusContext.java:174)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.<init>(JDOPersistenceManagerFactory.java:364)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.createPersistenceManagerFactory(JDOPersistenceManagerFactory.java:294)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.getPersistenceManagerFactory(JDOPersistenceManagerFactory.java:195)
        ... 12 more

它指向的行是PersistenceManagerFilter init方法:

pmf = JDOHelper.getPersistenceManagerFactory(getProperties());

属性文件如下所示:

    javax.jdo.PersistenceManagerFactoryClass=org.datanucleus.api.jdo.JDOPersistenceManagerFactory
datanucleus.ConnectionDriverName=org.h2.Driver
datanucleus.ConnectionURL=jdbc:h2:datanucleus
datanucleus.ConnectionUserName=sa
datanucleus.ConnectionPassword=

我拥有来自 maven 的所有依赖项,目标是使用依赖项进行部署。依赖关系如datanucleus页面http://www.datanucleus.org/products/datanucleus/jdo/maven.html

所述

有什么想法吗?

【问题讨论】:

  • 什么“可执行jar”?由什么组成?
  • 具有 maven 依赖项的整个项目部署为可执行 jar 文件。
  • 你的意思是你解开了 DN 罐子,把所有东西都放在一个罐子里?
  • 我已经把所有东西都打包到了大 jar 中,所有的依赖 jar 都打包到了可执行的 jar 中。在 jar 中使用 maven-repo 样式结构用于依赖项。捆绑所有内容的正确方法是什么,这样我就可以拥有工作 jar,并且所有依赖项都正常工作?
  • 不,我的清单文件中没有。我不是在创建一个插件,只是一个独立的 java 应用程序,所以我没有看那部分文档。我真的不知道该放什么,捆绑信息,还是只定义导入?

标签: java jdo datanucleus


【解决方案1】:

DataNucleus jars 都支持 OSGi 并使用插件机制来识别功能,因此包含 plugin.xmlMETA-INF/MANIFEST.MF 文件。这些需要位于与原始 DN jar 相同的位置(从 jar 的根目录)。如果您解压缩然后重新打开它们,您将需要从 DN jar 中合并任何 plugin.xml 和 META-INF/MANIFEST.MF ...所有信息,而不仅仅是其中的一些信息。

【讨论】:

  • 好的,我现在很确定我的 jar 是正确的并且包含所有必需的信息。我想我在属性中遗漏了一些东西,它会是什么?或者他们是正确的?我已经编辑了我的帖子以包含所有属性。可能是关于缺少 datanucleus.ConnectionFactoryName 吗?它应该有什么价值?
  • 您能否更准确地了解合并这些文件的方法?不明显。
  • @DataNucleus 是的,解释合并清单文件的最佳/正确方法会很棒。我在一个大项目中编译了一个带阴影的 JAR,需要手动合并的东西太多了
  • @jtravaglini。 MANIFEST 信息是 OSGi,因此任何 OSGi 资源都应该在这方面为您提供帮助(DataNucleus 不会明确使用它,并且当您在 AFAIK 中出现一些错误时不会停止工作)。 plugin.xml 应该很明显如何合并(作为一个 XML 文件)......将所有扩展点放在顶部(从所有被合并的 plugin.xml 文件中),然后将所有扩展放在下面(以及每个扩展的所有条目一起扩展)。
【解决方案2】:

添加到 DataNucleus 答案。
为了达到你所需要的,你应该使用 ma​​ven-dependency-plugin
并将以下内容添加到您的 pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.4</version>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/jars</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

然后依赖项将在 target/jars 目录中。

要执行您的应用,请使用命令:

Windows:
java -cp "yourFile.jar;jars/*" package.className

Linux:
java -cp "yourFile.jar:jars/*" package.className

注意:不要使用 jars/*.jar,这不起作用

【讨论】:

    【解决方案3】:

    为了在需要单个 jar 的 Apache Storm 拓扑中使用 DataNucleus 4.x,我必须进行两次 hack 以保持他们的 PluginRegistry 工作正常。问题是 DataNucleus 核心尝试将模块加载为 OSGi 包,即使它没有在 OSGi 容器中运行。只要 jar 没有被合并,它就可以正常工作(我不想合并我的依赖项,但这不是我的选择)。

    首先,我将所有 plugin.xml 文件合并到 datanucleus-core plugin.xml 中。诀窍是扩展点 id 是相对于其父插件的 id 的。因此,如果您正在使用的任何模块定义新的扩展点,例如datanucleus-rdbms,您必须重写 id,以便它们与新的父插件相关。

    其次,我在 jar 的 MANIFEST.MF 中添加了以下条目:

    Premain-Class: org.datanucleus.enhancer.DataNucleusClassFileTransformer
    Bundle-SymbolicName: org.datanucleus;singleton:=true
    

    这个解决方案并不理想,因为我们的应用程序本质上是在伪装成 DataNucleus 核心 OSGi 包。然而,这就是我在休息几天后把头砸在桌子上的结果。

    也许可以提供不同的 PluginRegistry 实现,但我没有对此进行研究。

    【讨论】:

    • 你能解释一下哪些ID吗?
    【解决方案4】:

    对于其他努力合并 datanucleus plugin.xml 文件的人,我使用以下代码提供帮助。使用此命令从 3 个单独的 datanucleus plugin.xml 文件中传输内容,这将告诉您哪里有明确需要合并的扩展:

    cat plugin_core.xml plugin_rdbms.xml plugin_api.xml | grep -h "extension point" | tr -d "[:blank:]"| sort | uniq -d

    更多详情请见separate post

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多