GAE - Unowned relationship - when using begin and commit transtion exception: "can't operate on multiple entity groups in a single transaction.found both Element"

50 views
Skip to first unread message

Sono G. De M

unread,
Jul 28, 2012, 2:30:05 PM7/28/12
to google-a...@googlegroups.com
Hi,
When saving an entity with an unowned relationship, GAE seems to dislike to persist this composite entity when the pm.makeperistent(object) call is triggered from within a beginTxn() commitTxn().
I am using  datanucleus-appengine-2.0.1.jar with JDO.

Summary entities used in the test case:
(1) Entity CashFlowCategory is independent and has its own entity group
(2) Entity User is idependent an has its own entity group
(3) Entity CashFlow belongs to the user's entity group (part of a user's hierarchy of objects), and, additionally, it is also composed by an Unowned relationship with CashFlowCategory because, as stated in (1), Cashflow is an different entity group other than CashflowCategory. The CashflowCategory, evidently, is an entity that has no knowledge of teh CashFlow entities. So it is an unowned unidirectional relationship.


Summary of the testcase:
In the test that is blowing a apart several begin() commit() transactions are triggered, always saving data in no more than one entity group at a time.
Let's say that we reach a point in time where User and CashflowCategories are already persisted and that is time to create a new object of type CashFlow.
By creating this object and properly linking it in the hierarchy that it belongs to we should only be modifying the User entity group. The cashflow goes in the User's descedents hierarchy, on the other hand the CashflowCategory entity group continues blind as to teh fact that a Cashflow entity referencing it.
In particular, the cashflow is added to a cointainer belonging to the User Entity Group.
Outcomes of test:
(1) If I simply issue the pm.makePersitent(cashflow); 
My test is successful.

(2) If instead I do beginTxn(pm); pm.makePersitent(cashflow);  commitTxn(pm);
Then  GAE rejects the transaction by stating that I am trying to make changes to the User and Cashflowcategory entity groups, which should be false.
In fact, I can for example see in the GAE admin page that the cashflow entity is correctly saved when I just trigger the makepersistent() call on the cashflow  while not enclosing it in a transaction.

Is this a known issue, or am I not seeing the whole picture correctly?




javax.jdo.JDOException: can't operate on multiple entity groups in a single transaction.found both Element {
  type: "CashFlowCategory"
  id: 1
}
 and Element {
  type: "User"
  id: 3
}

at org.datanucleus.api.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:567)
at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:163)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest$1MethodImplementation.commitTxn(SaveUserWithCashFlowDataTest.java:208)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest$1MethodImplementation.execute(SaveUserWithCashFlowDataTest.java:250)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest.testCreateUserWithCashFlowDataSimpleImpl(SaveUserWithCashFlowDataTest.java:262)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest.testCreateUserWithCashFlowDataSimple(SaveUserWithCashFlowDataTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)
NestedThrowablesStackTrace:
java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction.found both Element {
  type: "CashFlowCategory"
  id: 1
}
 and Element {
  type: "User"
  id: 3
}

at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:36)
at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:76)
at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:106)
at com.google.appengine.api.datastore.FutureHelper$CumulativeAggregateFuture.get(FutureHelper.java:145)
at com.google.appengine.api.datastore.FutureHelper$TxnAwareFuture.get(FutureHelper.java:222)
at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:90)
at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:90)
at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:72)
at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:59)
at com.google.appengine.api.datastore.DatastoreServiceImpl.get(DatastoreServiceImpl.java:55)
at com.google.appengine.datanucleus.WrappedDatastoreService.get(WrappedDatastoreService.java:70)
at com.google.appengine.datanucleus.EntityUtils.getEntityFromDatastore(EntityUtils.java:665)
at com.google.appengine.datanucleus.DatastorePersistenceHandler.updateObject(DatastorePersistenceHandler.java:419)
at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3874)
at org.datanucleus.ObjectManagerImpl.flushInternalWithOrdering(ObjectManagerImpl.java:3797)
at org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:3720)
at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:3666)
at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:4050)
at org.datanucleus.ObjectManagerImpl$2.transactionPreCommit(ObjectManagerImpl.java:398)
at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:370)
at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:259)
at org.datanucleus.api.jdo.JDOTransaction.commit(JDOTransaction.java:96)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest$1MethodImplementation.commitTxn(SaveUserWithCashFlowDataTest.java:208)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest$1MethodImplementation.execute(SaveUserWithCashFlowDataTest.java:250)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest.testCreateUserWithCashFlowDataSimpleImpl(SaveUserWithCashFlowDataTest.java:262)
at pt.ninetyninesono.expenses.model.entities.SaveUserWithCashFlowDataTest.testCreateUserWithCashFlowDataSimple(SaveUserWithCashFlowDataTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
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)


Reply all
Reply to author
Forward
0 new messages