簡體   English   中英

Datanucleus、JDO 和可執行文件 jar - 怎么做?

[英]Datanucleus, JDO and executable jar - how to do it?

我正在為嵌入式 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所述

有任何想法嗎?

DataNucleus jars 都啟用了 OSGi,並使用插件機制來識別功能,因此包含plugin.xmlMETA-INF/MANIFEST.MF文件。 這些需要位於與原始 DN jars(來自 jar 的根目錄)中相同的位置。 如果您解壓然后重新打包它們,您將需要合並來自 DN jars 的任何 plugin.xml 和 META-INF/MANIFEST.MF ...所有信息,而不僅僅是其中的一部分。

添加到 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,這將不起作用

為了在需要單個 jar 的 Apache Storm 拓撲中使用 DataNucleus 4.x,我不得不進行兩次 hack 以保持其 PluginRegistry 工作正常。 問題是 DataNucleus 核心會嘗試將模塊作為 OSGi 包加載,即使它沒有在 OSGi 容器中運行。 只要不合並 jars 就可以正常工作(我不希望合並我的依賴項,但這對我來說不是一個選項)。

首先,我將所有 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 實現,但我沒有研究過這個。

對於努力合並 datanucleus plugin.xml 文件的其他任何人,我使用以下代碼來提供幫助。 Pipe 來自 3 個單獨的 datanucleus plugin.xml 文件的內容使用此命令,這將告訴您哪里有明確需要合並的擴展:

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

更多詳細信息在單獨的帖子中。

基於現有答案(尤其是https://stackoverflow.com/a/27030103/1571826 ),使用 RDBMS 插件的 ID 手動覆蓋我的plugin.xml一次。 為此,我遵循了這個答案: https://stackoverflow.com/a/37511856/1571826

將新plugin.xml存儲為資源后,我按如下方式配置了maven-shade-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <finalName>${project.artifactId}-shaded</finalName>
                <filters>
                    <filter>
                        <artifact>*:*</artifact>
                        <excludes>
                            <exclude>META-INF/*.SF</exclude>
                            <exclude>META-INF/*.DSA</exclude>
                            <exclude>META-INF/*.RSA</exclude>
                            <exclude>META-INF/DEPENDENCIES</exclude>
                            <exclude>META-INF/license/*</exclude>
                            <exclude>META-INF/LICENSE</exclude>
                            <exclude>META-INF/NOTICE</exclude>
                        </excludes>
                    </filter>
                </filters>
                <transformers>
                    <!--
                    Metastore dependencies require below highly specific merging solutions:
                    - https://github.com/apache/iceberg/issues/5946#issuecomment-1278674526
                    - https://stackoverflow.com/a/10106373/1571826
                    - https://stackoverflow.com/a/37511856/1571826
                    -->
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                        <resource>META-INF/MANIFEST</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                        <manifestEntries>
                            <Main-Class>${mainClass}</Main-Class>
                            <Premain-Class>org.datanucleus.enhancer.DataNucleusClassFileTransformer</Premain-Class>
                            <Bundle-SymbolicName>org.datanucleus;singleton:=true</Bundle-SymbolicName>
                        </manifestEntries>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                        <resource>plugin.xml</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
                        <resource>plugin.xml</resource>
                        <file>src/main/resources/plugin.xml</file>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>reference.conf</resource>
                    </transformer>
                </transformers>
            </configuration>
        </plugin>
    </plugins>
</build>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM