2010-02-19 5 views
6

Warum ergibt sich der folgende Code in org.datanucleus.exceptions.NucleusUserException: Object Manager wurde geschlossen? Die Ausnahme scheint bei query.getResultList() ausgelöst zu werden.Google App Engine - org.datanucleus.exceptions.NucleusUserException: Der Objektmanager wurde geschlossen

public final void removeUserTokens(final String username) { 
    final Query query = entityManager.createQuery(
     "SELECT p FROM PersistentLogin p WHERE username = :username"); 
    query.setParameter("username", username); 

    for (Object token : query.getResultList()) { 
     entityManager.remove(token); 
    } 
}   

Ausnahme:

org.datanucleus.exceptions.NucleusUserException: Object Manager has been closed 
at org.datanucleus.ObjectManagerImpl.assertIsOpen(ObjectManagerImpl.java:3876) 
at org.datanucleus.ObjectManagerImpl.getFetchPlan(ObjectManagerImpl.java:376) 
at org.datanucleus.store.query.Query.getFetchPlan(Query.java:497) 
at org.datanucleus.store.appengine.query.DatastoreQuery$6.apply(DatastoreQuery.java:611) 
at org.datanucleus.store.appengine.query.DatastoreQuery$6.apply(DatastoreQuery.java:610) 
at org.datanucleus.store.appengine.query.LazyResult.resolveNext(LazyResult.java:94) 
at org.datanucleus.store.appengine.query.LazyResult$LazyAbstractListIterator.computeNext(LazyResult.java:215) 
at org.datanucleus.store.appengine.query.AbstractIterator.tryToComputeNext(AbstractIterator.java:132) 
at org.datanucleus.store.appengine.query.AbstractIterator.hasNext(AbstractIterator.java:127) 
at org.datanucleus.store.appengine.query.LazyResult$AbstractListIterator.hasNext(LazyResult.java:169) 
at com.mystuff.service.auth.PersistentTokenRepositoryImpl.removeUserTokens(PersistentTokenRepositoryImpl.java:90) 

bearbeiten: Ich habe das Log-Level erhöht für Datanucleus und das ist, was ich sehe.

FINE: Object Manager "[email protected]" opened for datastore "[email protected]" 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl initialiseLevel1Cache 
FINE: Level 1 Cache of type "weak" initialised 
Feb 25, 2010 7:21:38 AM org.datanucleus.JDOClassLoaderResolver classForName 
FINE: Class "java.lang.PersistentLogin" was not found in the CLASSPATH [Class resolver called from org.datanucleus.util.Imports.resolveClassDeclaration (line=177)] 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl disconnectSMCache 
FINE: Level 1 Cache cleared 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl postClose 
FINE: Object Manager "[email protected]" closed 
Feb 25, 2010 7:21:38 AM com.google.apphosting.utils.jetty.JettyLogger warn 
WARNING: /j_spring_security_logout 
Object Manager has been closed 
org.datanucleus.exceptions.NucleusUserException: Object Manager has been closed 
at org.datanucleus.ObjectManagerImpl.assertIsOpen(ObjectManagerImpl.java:3876) 
at org.datanucleus.ObjectManagerImpl.getFetchPlan(ObjectManagerImpl.java:376) 

Antwort

3

Das Hinzufügen von @Transactional zu der Methode verhindert, dass der Objektmanager geschlossen wird. Ich bin mir jedoch nicht sicher, warum es ohne dieses schließt.

+1

Annahme @Transactional ist von Springframework –

+0

org.springframework.transaction.annotation.Transactional –

0

Ich weiß nicht, warum genau, aber es scheint mit query.getResultList() faul-geladen zu tun zu haben. Offenbar bricht das Lazy-Loading beim Aufruf remove(token) zusammen.

Als Workaround können Sie zunächst die IDs/Schlüssel für die Elemente in einer ArrayList sammeln und sie dann in einer separaten Schleife aus dem Datenspeicher entfernen?

+0

Hmmm, die Ausnahme bei getResultList geworfen wird(), um die IDs sammeln/Tasten noch eine getResultList erfordern würde () Anruf, von dem ich annehme, dass er scheitern würde. Ich habe das Gefühl, dass ich ein größeres Problem habe, das mit der Art und Weise zusammenhängt, wie Spring und GAE interagieren. –

+0

Der Unterschied ist, dass das Laden der Instanzen (was passiert, wenn Sie über die Ergebnisliste in Iterator.hasNext(), nicht in getResultList()) iterieren, nicht mit den remove() -Aufrufen verschachtelt wäre. – Thilo