2010-02-19 12 views
6

Pourquoi le code ci-dessous aboutit à org.datanucleus.exceptions.NucleusUserException: le gestionnaire d'objets a été fermé? L'exception semble être lancée sur query.getResultList().Google App Engine - org.datanucleus.exceptions.NucleusUserException: le gestionnaire d'objets a été fermé

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

Exception:

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) 

Modifier: J'augmenté le niveau de journalisation pour DataNucleus et voici ce que je vois.

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) 

Répondre

3

Cependant, je ne suis pas sûr pourquoi il se ferme sans cela.

+1

en supposant que @Transactional provient de springframework –

+0

org.springframework.transaction.annotation.Transactional –

0

Je ne sais pas exactement pourquoi, mais il semble avoir à voir avec query.getResultList() être chargé paresseux. Apparemment, le chargement paresseux se décompose lorsque vous appelez remove(token). En guise de solution de rechange, pouvez-vous d'abord collecter les identifiants/clés pour les éléments d'une ArrayList, puis les supprimer du magasin de données dans une boucle distincte? L'ajout de @Transactional à la méthode empêche la fermeture du gestionnaire d'objets.

+0

Hmmm, l'exception est levée à getResultList() pour la collecte des ids/clés auraient encore besoin d'un getResultList () appel que je suppose échouerait. J'ai l'impression d'avoir un problème plus important lié à la façon dont Spring et GAE interagissent. –

+0

la différence est que le chargement des instances (ce qui se produit lorsque vous parcourez la liste de résultats dans Iterator.hasNext(), pas dans getResultList()) ne serait pas entrelacé avec les appels remove(). – Thilo