5

В моем проекте (Spring Framework + Google App Engine + DataNucleus + JPA) я получаю следующее исключение при запуске сервера:Как настроить зависимости для DataNucleus AppEngine plugin v3?

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 ищет метод, который даже не существовал? Я не могу это получить.

Dora
Помогите DataNucleus и мне найти недостающий способ!


UPDATE
Как Neil Stockton отметил, что это потому, что я использую несовместимые версии DataNucleus-ядра и DataNucleus-Апи-JPA. Но я не знаю правильной комбинации зависимостей. И я начинаю думать, что DataNucleus App Engine Plugin 3.0 в настоящее время не готов к использованию.


Я хочу использовать DataNucleus App Engine Plugin 3.0 из this issue (фиксировано в DataNucleus версиях 3.2.6 и 3.3.3) и потому что мне нужно JPA 2.1 функции (выборка групп/графики сущностей). Модуль Plugin 3.0 для модулей приложений DataNucleus имеет compatible с упомянутыми версиями DataNucleus, но неиздано. Я проверил плагин из SVN, упаковал его и добавил в свой проект как банку (идентичная банка доступна для download, если вы хотите повторить эту настройку самостоятельно).

сборка.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" 
} 

Spring контекст:

<?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> 

UPDATE:
Если я ставлю DataNucleus-Апи-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) 

Из документации:

Приложение Engine Java SDK включает в себя версии 2.x плагин DataNucleus для App Engine. Этот плагин соответствует версии 3.0 платформы доступа DataNucleus, которая позволяет использовать хранилище App Engine через JPA 2.0.
JPA представляет собой стандартный интерфейс для взаимодействия с реляционными базами данных, но хранилище данных App Engine не является реляционной базой данных. В результате есть функции JPA, которые App Engine просто не может поддерживать.

+0

с использованием несовместимых версий DataNucleus-ядра и DataNucleus-Апи-JPA. Spring не делает этот вызов, как показывает ваша трассировка стека, вызывается org.datanucleus.api.jpa.XXX –

ответ

0

Простой факт заключается в том, что вам необходимо использовать согласованные версии различных банок. Если вы используете Google datanucleus-appengine v3.0 (SVN), то вы ДОЛЖНЫ иметь проект DataNucleus «datanucleus-core», «datanucleus-api-jpa» v3.2.x (или 3.3.x of datanucleus-api-jpa) и других версий. Если вы получили сообщение о

Плагин (Bundle) "org.datanucleus.api.jpa" уже зарегистрирован.

, то у вас есть несколько версий этого плагина в CLASSPATH, и вы должны исправить свои CLASSPATH (просто распечатать то, что находится в CLASSPATH и он расскажет вам ... что-то вроде System.getProperty ("java.class .дорожка")).

В вашем случае у вас есть

файл: //appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1 .3.jar

и

файл: //caches/modules-2/files-2.1/org.datanucleus/datanucleus-api-jpa/3.2.2/c24c14634c39b5b9a59dcd379dbb6d93da97f3e7/datanucleus-api -jpa-3.2.2.jar

так избавиться от первого одного

+0

, и если это не дает успеха, тогда нормальная вещь - сказать, что «не работает», когда вы это делаете , –