Datanucleus,JDO和可执行jar - 怎么做?

时间:2012-04-10 21:33:54

标签: java jdo datanucleus

我正在使用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

所述

有什么想法吗?

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分: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,这不会起作用

答案 2 :(得分:2)

为了在需要单个jar的Apache Storm拓扑中使用DataNucleus 4.x,我必须做两次黑客攻击才能保持PluginRegistry的工作。问题是DataNucleus核心尝试将模块加载为OSGi包,即使它没有在OSGi容器中运行。只要罐子没有合并(我宁愿不合并我的依赖关系,但这不是我的选择),这种方法很好。

首先,我将所有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实现,但我没有考虑过这个。

答案 3 :(得分:1)

见一罐。 This post on the DataNucleus forum解释得很清楚。

答案 4 :(得分: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

更多详细信息位于separate post中。