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)
--
You received this message because you are subscribed to the Google Groups
"Google App Engine" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/google-appengine/-/fa4i30IupQgJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-appengine?hl=en.