2010-02-19 16 views
6

Perché il codice sottostante risulta in org.datanucleus.exceptions.NucleusUserException: Object Manager è stato chiuso? L'eccezione sembra essere generata su query.getResultList().Google App Engine - org.datanucleus.exceptions.NucleusUserException: Object Manager è stato chiuso

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); 
    } 
}   

Eccezione:

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) 

Edit: ho aumentato il livello di registro per DataNucleus e questo è quello che vedo.

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) 

risposta

3

L'aggiunta del metodo @Transactional al metodo impedisce la chiusura del gestore oggetti. Tuttavia, non sono sicuro del motivo per cui si chiude senza questo.

+1

assumendo che @Transactional provenga da springframework –

+0

org.springframework.transaction.annotation.Transactional –

0

Non so esattamente perché, ma sembra avere a che fare con query.getResultList() essere pigro-caricato. Apparentemente il pigro caricamento si interrompe quando chiami remove(token).

Come soluzione, è possibile raccogliere prima gli id ​​/ chiavi per gli elementi in un oggetto ArrayList e in un ciclo separato rimuoverli dal datastore?

+0

Hmmm, l'eccezione viene lanciata contro getResultList() in modo da raccogliere le IDS/chiavi sarebbe ancora bisogno di una getResultList () chiamata che presumo fallirebbe. Mi sembra di avere un problema più grande in corso correlato al modo in cui Spring e GAE interagiscono. –

+0

la differenza è che il caricamento delle istanze (che si verifica quando si esegue l'iterazione nell'elenco dei risultati in Iterator.hasNext(), non in getResultList()) non viene interfogliato con le chiamate remove(). – Thilo