【问题标题】:How to configure dependencies for DataNucleus AppEngine plugin v3?如何为 DataNucleus AppEngine 插件 v3 配置依赖项?
【发布时间】:2015-07-01 15:57:32
【问题描述】:

在我的项目(Spring Framework + Google App Engine + DataNucleus + JPA)中,服务器启动时出现以下异常:

WARNING: Nestedin org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; 
    nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in ServletContext resource [/WEB-INF/spring/db.xml]: Invocation of init method failed; 
    nested exception is java.lang.NoSuchMethodError: org.datanucleus.metadata.MetaDataUtils.parsePersistenceFiles(Lorg/datanucleus/plugin/PluginManager;Ljava/lang/String;ZLorg/datanucleus/NucleusContext;)[Lorg/datanucleus/metadata/PersistenceFileMetaData;:
java.lang.NoSuchMethodError: org.datanucleus.metadata.MetaDataUtils.parsePersistenceFiles(Lorg/datanucleus/plugin/PluginManager;Ljava/lang/String;ZLorg/datanucleus/NucleusContext;)[Lorg/datanucleus/metadata/PersistenceFileMetaData;
    at org.datanucleus.api.jpa.JPAEntityManagerFactory.<init>(JPAEntityManagerFactory.java:342)
    at org.datanucleus.api.jpa.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:91)

很明显这个异常是在persistence.xml解析过程中抛出的。 Spring 尝试调用方法MetaDataUtils#parsePersistenceFiles(PluginManager,String,NucleusContext,nucCtx),但它不存在。此方法是org.datanucleus:datanucleus-core 的一部分。起初我以为我在某处缺少或重复的依赖项。我已经执行了

gradle dependencies

仔细扫描输出,没有发现任何可疑之处:只有一个版本的依赖项。
根据文档MetaDataUtils 只有一个parsePersistenceFiles 方法:

public static PersistenceFileMetaData[] parsePersistenceFiles(
  PluginManager pluginMgr, String persistenceFilename, boolean validate, ClassLoaderResolver clr);

如果您细心,您可能已经注意到它的参数不同:有一个额外的boolean validate 参数。奇怪的是,在任何版本的 DataNucleus 中都没有这种方法。 DataNucleus 为什么要寻找甚至不存在的方法?看不懂。


请帮助我和 DataNucleus 找到丢失的方法!


更新
正如Neil Stockton 指出的那样,这是因为我使用的 datanucleus-core 和 datanucleus-api-jpa 版本不一致。但我不知道正确的依赖组合。我开始思考,DataNucleus App Engine Plugin 3.0 目前还没有准备好使用。


我想使用 DataNucleus App Engine 插件 3.0,因为 this issue(在 DataNucleus 版本 3.2.6 和 3.3.3 中已修复)并且因为我需要 JPA 2.1 功能(获取组/实体图)。 DataNucleus App Engine 插件 3.0 是 compatible,带有提到的 DataNucleus 版本,但未发布。我已从 SVN 签出插件,将其打包,并作为 jar 添加到我的项目中(download 可以使用相同的 jar,如果您想自己重复此设置)。

build.gradle:

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'appengine'

dependencies {
    // App Engine
    compile fileTree(dir: 'libs', include: ['*.jar'])  // There is datanucleus-appengine-3.0.0-20140128.jar in libs
    appengineSdk 'com.google.appengine:appengine-java-sdk:1.9.19'
    compile 'com.google.appengine:appengine-api-1.0-sdk:1.9.19'
    
    // persistence
    // App Engine and DataNucleus compatibility:
    // https://code.google.com/p/datanucleus-appengine/wiki/Compatibility
    compile 'org.eclipse.persistence:javax.persistence:2.1.0'
    runtime 'org.datanucleus:datanucleus-core:3.2.15'
    compile 'org.datanucleus:datanucleus-api-jpa:3.1.3'
    compile 'javax.jdo:jdo-api:3.1'
    compile 'org.datanucleus:datanucleus-jodatime:3.2.1'

    // Spring Framework
    compile("org.springframework:spring-webmvc:4.1.6.RELEASE")
    compile ("org.springframework.data:spring-data-jpa:1.8.0.RELEASE")
    providedCompile 'javax.annotation:javax.annotation-api:1.2'

    compile 'com.google.code.gson:gson:2.3.1'
    providedCompile 'org.projectlombok:lombok:1.16.+'
}

appengine {
    downloadSdk = true
    httpAddress = "0.0.0.0"
}

弹簧上下文:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
    default-autowire="byName">
    <jpa:repositories base-package="<my.package.name>.repositories" />

    <!-- The simplest and the most limited form of JPA deployment -->
    <!-- For details see http://docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html#orm-jpa -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="transactions-optional" />
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

持久化单元

<persistence-unit name="transactions-optional">
    <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
    <properties>
        <property name="datanucleus.NontransactionalRead" value="true" />
        <property name="datanucleus.NontransactionalWrite" value="true" />
        <property name="datanucleus.ConnectionURL" value="appengine" />
        <property name="datanucleus.appengine.datastoreEnableXGTransactions" value="true" />
    </properties>
</persistence-unit>

更新:
如果我把另一个版本的datanucleus-api-jpa放在CLASSPATH上,例如

compile 'org.datanucleus:datanucleus-api-jpa:3.2.2'

我在增强过程中遇到异常:

java.lang.RuntimeException: Unexpected exception
    at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:76)
    at com.google.appengine.tools.enhancer.Enhance.<init>(Enhance.java:71)
    ... 1 more
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    ... 5 more
Caused by: org.datanucleus.exceptions.NucleusException: 
    Plugin (Bundle) "org.datanucleus.api.jpa" is already registered. 
    Ensure you dont have multiple JAR versions of the same plugin in the classpath.
    The URL "file:/<GRADLE_HOME>/appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1.3.jar" is already registered, 
    and you are trying to register an identical plugin located at URL "file:/<GRADLE_HOME>/caches/modules-2/files-2.1/org.datanucleus/datanucleus-api-jpa/3.2.2/c24c14634c39b5b9a59dcd379dbb6d93da97f3e7/datanucleus-api-jpa-3.2.2.jar."
    at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:541)
    at org.datanucleus.plugin.NonManagedPluginRegistry.registerBundle(NonManagedPluginRegistry.java:395)

来自文档:

App Engine Java SDK 包含适用于 App Engine 的 DataNucleus 插件 2.x 版。此插件对应于 DataNucleus 访问平台 3.0 版,可让您通过 JPA 2.0 使用 App Engine 数据存储区。
JPA 提供了与关系数据库交互的标准接口,但 App Engine 数据存储区不是关系数据库。因此,App Engine 根本无法支持 JPA 的某些功能。

【问题讨论】:

  • 使用不一致的 datanucleus-core 和 datanucleus-api-jpa 版本。 Spring 没有像您的堆栈跟踪所示那样进行该调用,由 org.datanucleus.api.jpa.XXX 调用

标签: google-app-engine dependencies spring-data-jpa datanucleus nosuchmethoderror


【解决方案1】:

简单的事实是您必须使用各种 jar 的一致版本。如果使用 Google 的“datanucleus-appengine”v3.0 (SVN),那么您必须拥有 DataNucleus 项目“datanucleus-core”、“datanucleus-api-jpa”v3.2.x(或 datanucleus-api-jpa 的 3.3.x ),没有其他版本。如果您收到有关

的消息

插件(Bundle)“org.datanucleus.api.jpa”已经注册。

那么你在 CLASSPATH 中有多个版本的插件,你应该修复你的 CLASSPATH(只需打印出 CLASSPATH 中的内容,它会告诉你......类似 System.getProperty("java.class.path" ))。

在你的情况下,你有

file://appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1.3.jar

file://caches/modules-2/files-2.1/org.datanucleus/datanucleus-api-jpa/3.2.2/c24c14634c39b5b9a59dcd379dbb6d93da97f3e7/datanucleus-api-jpa-3.2.2.jar

所以摆脱第一个

【讨论】:

  • 如果这没有成功,那么正常的做法是在你这样做的时候说什么“不起作用”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-23
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多