5

In meinem Projekt (Spring Framework + Google App Engine + Datanucleus + JPA) ich die folgende Ausnahme auf dem Serverstart erhalten:Wie konfiguriert man Abhängigkeiten für 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) 

Offensichtlich ist diese Ausnahme bei persistence.xml Parsing throwed wird. Spring versucht, Methode MetaDataUtils#parsePersistenceFiles(PluginManager,String,NucleusContext,nucCtx) aufzurufen, aber es fehlt. Diese Methode ist Teil von org.datanucleus:datanucleus-core. Zuerst dachte ich, dass ich irgendwo eine fehlende oder doppelte Abhängigkeit habe. Ich habe

ausgeführt
gradle dependencies 

sorgfältig gescannt Ausgang und fand nichts Verdächtiges: nur eine einzige Version der Abhängigkeit.
Gemäß der Dokumentation MetaDataUtils hat nur eine parsePersistenceFiles Methode:

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

Wenn Sie aufmerksam sind, haben Sie wahrscheinlich bemerkt, dass es in Argumente unterscheidet: es gibt ein extra boolean validate Argument. Merkwürdigerweise gibt es in keiner Version von DataNucleus eine solche Methode. Warum sucht DataNucleus nach der Methode, die es noch gar nicht gibt? Ich verstehe es nicht.

Dora
Bitte helfen Sie DataNucleus und ich finden die fehlende Methode!


UPDATE
Wie Neil Stockton wies darauf hin, es ist, weil ich inkonsistente Versionen von Datanucleus-Core und Datanucleus-api-JPA bin. Aber ich kenne die richtige Kombination von Abhängigkeiten nicht. Und ich fange an zu denken, dass DataNucleus App Engine Plugin 3.0 derzeit nicht zur Nutzung bereit ist.


Ich will Datanucleus App Engine Plugin 3.0 wegen this issue (fest in Datanucleus-Versionen 3.2.6 und 3.3.3) und weil ich brauche JPA 2.1-Funktionen (Fetch Gruppen/Einheit Graphen) verwenden. Das DataNucleus App Engine Plugin 3.0 ist compatible mit den erwähnten Versionen von DataNucleus, aber unveröffentlicht. Ich habe das Plugin aus SVN ausgecheckt, verpackt und zu meinem Projekt als jar hinzugefügt (ein identisches jar ist für download verfügbar, wenn Sie diese Einstellung selbst wiederholen möchten).

bauen.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" 
} 

Frühling Kontext:

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

Persistenzeinheit

<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:
Wenn ich setzen Datanucleus-api-JPA einer anderen Version auf CLASSPATH zum Beispiel

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

Ich erhalte eine Ausnahme während der Erweiterung:

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) 

Aus Dokumentation:

Die App Engine Java SDK enthält Version 2.x der Datanucleus-Plugin für App Engine. Dieses Plugin entspricht Version 3.0 der DataNucleus Access Platform, mit der Sie den App Engine-Datenspeicher über JPA 2.0 verwenden können.
JPA stellt eine Standardschnittstelle für die Interaktion mit relationalen Datenbanken bereit, der App Engine-Datenspeicher ist jedoch keine relationale Datenbank. Daher gibt es Funktionen von JPA, die App Engine einfach nicht unterstützen kann.

+0

inkonsistente Versionen von Datanucleus-Core und Datanucleus-api-JPA verwenden. Spring macht diesen Aufruf nicht, wie Ihr Stack-Trace zeigt, der von org.datanucleus.api.jpa.XXX –

Antwort

0

Die einfache Tatsache ist, dass Sie konsistente Versionen der verschiedenen Gläser verwenden müssen. Wenn Sie das "datanucleus-appengine" v3.0 (SVN) von Google verwenden, dann MÜSSEN Sie das DataNucleus-Projekt "datanucleus-core", "datanucleus-api-jpa" v3.2.x (oder 3.3.x des datanucleus-api-jpa) und keine anderen Versionen. Wenn Sie eine Nachricht über

erhalten

Plugin (Bundle) "org.datanucleus.api.jpa" ist bereits registriert.

dann haben Sie mehrere Versionen dieses Plugin in der CLASSPATH und Sie sollten Ihre CLASSPATH FIX (nur drucken, was in der CLASSPATH ist und es wird Ihnen sagen ... so etwas wie System.getProperty ("java.class .Pfad")).

In Ihrem Fall haben Sie

Datei: //appengine-sdk/appengine-java-sdk-1.9.19/lib/opt/tools/datanucleus/v2/datanucleus-api-jpa-3.1 .3.jar

und

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

so loszuwerden des ersten

+0

aufgerufen wird und wenn dies keinen Erfolg bringt, dann ist es normal zu sagen, was "nicht funktioniert", wenn Sie es tun . –

Verwandte Themen