dipaksavaliya / datanucleus-appengine

Automatically exported from code.google.com/p/datanucleus-appengine
0 stars 0 forks source link

datanucleus.DetachAllOnCommit doesn't work properly #151

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
As per Andy Jefferson response to my query about why it's not working (my 
sample test follows):

So ask the question (of Google) why is "StreamingQueryResult".size
trying to find the next result when the PM (and ObjectManager) has
already been closed (by Spring). When a "query result" (of which
StreamingQueryResult is one example) is handed to the user it should
have registered a callback to be informed when an owning PM is being
closed, and so to have the opportunity to read in all results when
that happens, so that it doesn't need to subsequently. Nothing to do
with detachAllOnCommit.

You could also mention that StreamingQueryResult ought to implement
Serializable, so then people don't need to waste their time having to
copy results into their own ArrayList, and hence be more compliant
with JDO/JPA specs.

+!+!+!+!+!+!+!+!+!+!+!

I'm setting datanucleus.DetachAllOnCommit in my jdoconfig.xml file.  Why 
am I getting "Object Manager has been closed" when I do a query that finds 
all entities of a specific class?  Is it because I'm not using a 
transaction?  Previously, before I added datanucleus.DetachAllOnCommit, my 
dao was doing a "return (getPersistenceManager().detachCopy(result));" for 
all find (read-only) queries and didn't get any errors.

=====================================================================

<jdoconfig
   xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

   <persistence-manager-factory name="transactions-optional">
       <!-- omitted other stuff that was already in here, from google -->

       <property
           name="datanucleus.DetachAllOnCommit"
           value="true"
       />
   </persistence-manager-factory>

=====================================================================
//dao class, extends org.springframework.orm.jdo.support.JdoDaoSupport

   public List<E> findAll() {
       final Query query = newQuery();

       @SuppressWarnings("unchecked")
       final List<E> results = (List<E>) (query.execute());

       return (results);
   }

   private Query newQuery() {
       return (getPersistenceManager().newQuery(this.entityClass));
   }

=====================================================================

   @Before
   public void insertUser() throws Exception {
       final int entityCountBefore = this.testUtils.entityCounter
(User.class);

       Assert.assertEquals("entityCount was not 0", 0, entityCountBefore);

       final User user1 = new User(this.userName, Long.valueOf(999L));

       this.persistedUser1 = this.userDao.makePersistent(user1);

       this.log.debug("user1: {}, persistedUser1: {}", user1, 
this.persistedUser1);

       final User user2 = new User(this.userName + "-2", Long.valueOf
(999L));

       this.persistedUser2 = this.userDao.makePersistent(user2);

       final int entityCountAfter = this.testUtils.entityCounter
(User.class);

       this.log.debug("entityCountAfter: {}", Integer.valueOf
(entityCountAfter));

       Assert.assertEquals("entityCount was not 2", 2, entityCountAfter);
   }

   @Test
   public void findAll() {
       final Collection<User> results = this.userDao.findAll();

       Assert.assertNotNull("results should not be null", results);

       // blows up on this statement, line 138
       Assert.assertTrue("results should not be empty", !results.isEmpty
());

       Assert.assertTrue("results should have 2 entries", results.size() 
== 2);

       final User result = results.iterator().next();

       this.log.debug("result: {}", result);
   }

=====================================================================

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$5.apply
(DatastoreQuery.java:508)
    at org.datanucleus.store.appengine.query.DatastoreQuery$5.apply
(DatastoreQuery.java:507)
    at 
org.datanucleus.store.appengine.query.StreamingQueryResult.resolveNext
(StreamingQueryResult.java:137)
    at org.datanucleus.store.appengine.query.StreamingQueryResult.size
(StreamingQueryResult.java:174)
    at org.datanucleus.store.query.AbstractQueryResult.isEmpty
(AbstractQueryResult.java:312)
    at com.objecteffects.waitlist.db.impl.dao.jdo.UserDaoTest.findAll
(UserDaoTest.java:138)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall
(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run
(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively
(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate
(InvokeMethod.java:20)
    at org.junit.internal.runners.statements.RunBefores.evaluate
(RunBefores.java:28)
    at 
org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallb
acks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.junit.internal.runners.statements.RunAfters.evaluate
(RunAfters.java:31)
    at 
org.springframework.test.context.junit4.statements.RunAfterTestMethodCallba
cks.evaluate(RunAfterTestMethodCallbacks.java:82)
    at 
org.springframework.test.context.junit4.statements.SpringRepeat.evaluate
(SpringRepeat.java:72)
    at 
org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild
(SpringJUnit4ClassRunner.java:240)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild
(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at 
org.springframework.test.context.junit4.statements.RunBeforeTestClassCallba
cks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at 
org.springframework.test.context.junit4.statements.RunAfterTestClassCallbac
ks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run
(SpringJUnit4ClassRunner.java:180)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run
(JUnit4TestReference.java:46)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run
(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests
(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run
(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main
(RemoteTestRunner.java:197)

=====================================================================
Spring transaction context xml config file.

<beans:beans
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:beans="http://www.springframework.org/schema/beans"
   xsi:schemaLocation="
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <!-- the transactionManager is declared in 
the                          -->
   <!-- src/main/resources/spring/jdo-<whatever>-context.xml 
file.         -->

   <!-- the transactional advice; what 'happens'; used by 
the              -->
   <!-- <aop:advisor/> 
bean.                                               -->
   <tx:advice id="transactionAdvice" transaction-
manager="transactionManager">
       <tx:attributes>
           <!-- for read only, propagation=NOT_SUPPORTED suspends 
any      -->
           <!-- current transaction, if there is one. I.e., read 
only      -->
           <!-- transactions are run without a transaction.  With 
this,    -->
           <!-- we can do queries on multiple unowned 
entities.            -->
           <tx:method
               name="find*"
               read-only="true"
               propagation="NOT_SUPPORTED"
           />

           <!-- always starts a transaction.  if any exception is 
thrown   -->
           <!-- the transaction is rolled 
back.                            -->
           <tx:method
               name="*"
               rollback-for="Throwable"
               propagation="REQUIRED"
           />
       </tx:attributes>
   </tx:advice>

   <aop:config>
       <aop:pointcut
           id="waitlistDaoOperation"
           expression="execution(* 
com.objecteffects.waitlist.db.api.dao.*.*(..))"
       />

       <aop:advisor
           advice-ref="transactionAdvice"
           pointcut-ref="waitlistDaoOperation"
       />
   </aop:config>
</beans:beans>

Original issue reported on code.google.com by rusty.wr...@gmail.com on 2 Nov 2009 at 1:56

GoogleCodeExporter commented 8 years ago
To clarify, StreamingQueryResult is indeed Serializable, just that GWT is very
limited in what it accepts and even if something extends an accepted class it 
loses
the plot - hence nothing is needed changing in StreamingQueryResult for making 
it
Serializable. The first comment about not loading results when the pm closes 
still
stands though

Original comment by googleco...@yahoo.co.uk on 10 Nov 2009 at 7:58

GoogleCodeExporter commented 8 years ago
SVN trunk no longer throws exceptions when accessing results beyond the scope 
of the PM. When the PM is being closed the query receives a notification and 
loads the remaining results

Original comment by googleco...@yahoo.co.uk on 15 Jul 2011 at 5:40