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
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.
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.
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 –