5

我正在为嵌入式 H2 数据库开发一个带有 Datanucleus 和 JDO 的桌面应用程序。当我从 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所述

有任何想法吗?

4

4 回答 4

6

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

于 2012-04-11T12:58:35.657 回答
2

为了在需要单个 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 实现,但我还没有研究过。

于 2014-11-20T01:16:20.297 回答
2

添加到 DataNucleus 答案。
为了满足您的需要,您应该使用maven-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,这不起作用

于 2012-04-13T08:02:16.667 回答
0

对于其他努力合并 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

更多详细信息在单独的帖子中。

于 2020-06-28T20:12:27.830 回答