It seems alarming to me that these basic relations are difficult to
code.  Lets face it, applications are full of these relations...it
seems to me that too much developer time is required in the
Persistence layer of GAE apps.  The Persistence and Presentation
layers needs to be a "no brainer", so more focus can be where it needs
to be - the business layer.  Does anyone feel the same?

On Sep 23, 7:51 pm, objectuser <kevin.k.le...@gmail.com> wrote:
> Here's some code that reproduces my problem.  Before the code, I think
> it's interesting to note that I started making this example in JPA
> (because I had an old test that used JPA) and I was not able to
> reproduce the error.  However, after converting to JDO, I get the
> error.  I'm not 100% sure the code is exactly the same, however, but
> wanted to note it in case it's helpful to anyone.
>
> LocalServiceTestCase is based on the examples from Google.
>
> Does anyone see a problem with the code or is this a legit bug?
>
> @PersistenceCapable(identityType = IdentityType.APPLICATION,
> detachable = "true")
> public class ParentOfOne {
>
>         @PrimaryKey
>         @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
>         private Long id;
>
>         @Persistent
>         private SharedChild child;
>         ...
>
> }
>
> @PersistenceCapable(identityType = IdentityType.APPLICATION,
> detachable = "true")
> public class ParentOfList {
>
>         @PrimaryKey
>         @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
>         private Long id;
>
>         @Persistent
>         private List<SharedChild> children;
>         ...
>
> }
>
> @PersistenceCapable(identityType = IdentityType.APPLICATION,
> detachable = "true")
> public class SharedChild {
>
>         @PrimaryKey
>         @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
>         private Key id;
>
>         @Persistent
>         private String name;
>         ...
>
> }
>
> public class SharedChildTestCase extends LocalServiceTestCase {
>
>         private PersistenceManager persistenceManager;
>
>         @Before
>         public void openPersistenceManager() {
>                 PersistenceManagerFactory persistenceManagerFactory = 
> JDOHelper
>                                 
> .getPersistenceManagerFactory("transactions-optional");
>                 persistenceManager = 
> persistenceManagerFactory.getPersistenceManager
> ();
>         }
>
>         @After
>         public void closePersitenceManager() {
>                 persistenceManager.close();
>         }
>
>         @Test
>         public void saveParents() {
>                 ParentOfList pol = new ParentOfList();
>                 List<SharedChild> list = new ArrayList<SharedChild>();
>                 SharedChild c1 = new SharedChild();
>                 c1.setName("c1");
>                 list.add(c1);
>                 SharedChild c2 = new SharedChild();
>                 c2.setName("c2");
>                 list.add(c2);
>                 pol.setChildren(list);
>                 persistenceManager.makePersistent(pol);
>
>                 ParentOfOne poo = new ParentOfOne();
>                 SharedChild c3 = new SharedChild();
>                 c1.setName("c3");
>                 poo.setChild(c3);
>                 persistenceManager.makePersistent(poo);
>         }
>
> }
>
> On Sep 22, 9:40 am, objectuser <kevin.k.le...@gmail.com> wrote:
>
>
>
> > Thanks, Marton.  That's very unfortunate.  The limitations still
> > surprise me.  Is that documented somewhere?  Need to go back and
> > reread that stuff I guess.
>
> > I'll see if I can come up with a simple test case for the collection.
>
> > On Sep 22, 3:28 am, Marton Papp <mapr...@gmail.com> wrote:
>
> > > A class cannot have two different owned relationship to a single
> > > class. For example if I have these two classes:
>
> > > @PersistenceCapable(identityType = IdentityType.APPLICATION)
> > > public class Parent3 {
>
> > >         @PrimaryKey
> > >         @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
> > >         private Long id;
>
> > >         Child1 child1;
>
> > >         Child1 child2;
>
> > > // ... get-set
>
> > > }
>
> > > @PersistenceCapable(identityType = IdentityType.APPLICATION)
> > > public class Child1 {
>
> > >     @PrimaryKey
> > >     @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
> > >     private Key id;
>
> > > // ... get-set
>
> > > }
>
> > > then this code will fail with an assertion error:
>
> > >         public void testMultiParent2() throws Exception {
>
> > >                 PersistenceManager pm;
>
> > >                 Parent3 p3 = null;
> > >                 Parent3 p3Loaded = null;
>
> > >                 pm = pmf.getPersistenceManager();
> > >                 pm.currentTransaction().begin();
>
> > >                 p3 = new Parent3();
> > >                 p3.setChild1(new Child1());
> > >                 p3.setChild2(new Child1());
> > >                 pm.makePersistent(p3);
> > >                 pm.currentTransaction().commit();
> > >                 pm.close();
>
> > >                 pm = pmf.getPersistenceManager();
> > >                 pm.currentTransaction().begin();
>
> > >                 p3Loaded = pm.getObjectById(Parent3.class, p3.getId());
>
> > >                 Assert.assertNotSame(p3Loaded.getChild1(), 
> > > p3Loaded.getChild2());
>
> > >                 pm.currentTransaction().commit();
> > >                 pm.close();
>
> > >         }
>
> > > It is because the datastore represents the relationship between Child1
> > > and Parent3 instances by making the Parent3 instance the parent of the
> > > Child1 instance. And it does the same for both Parent3.child1 and
> > > Parent3.child2 relationships, so there is no way to tell which
> > > property a particular instance of Child1 has been assigned to
> > > originally.
>
> > > I could not reproduce your problem with the list of children. Could
> > > you send some code that fails for you?
>
> > > Marton
>
> > > On Sep 22, 3:31 am, objectuser <kevin.k.le...@gmail.com> wrote:
>
> > > > After some more testing this is what I observe:
> > > > - If A has one C property and B has two C properties, I can save both
> > > > the A and the B instances, when I get the B instance, both C
> > > > properties point to the same instance of C.
> > > > - If A has one C property and B has a property that is a List of Cs, I
> > > > get the exception in my original post.
>
> > > > I guess I need to work this down to a repeatable example and file a
> > > > defect report.
>
> > > > On Sep 21, 2:49 pm, objectuser <kevin.k.le...@gmail.com> wrote:
>
> > > > > I'll let leszek talk more about the code, but I assumed that the
> > > > > commented out line was just testing both scenarios.  In the scenario
> > > > > without comment on the line, it would be my scenario: the same "owned
> > > > > type" but not the same "owned instance".
>
> > > > > My original question is not about one particular entity having two
> > > > > parents (in an owned relationship), but having two entity groups share
> > > > > the same "owned" Java type.
>
> > > > > Does that make sense?
>
> > > > > On Sep 21, 2:00 pm, Marton Papp <mapr...@gmail.com> wrote:
>
> > > > > > Hi,
>
> > > > > > The code in that form also works for me, but just because the
> > > > > > exception is caught and never reported. If you rethrow any 
> > > > > > exceptions
> > > > > > from the catch blocks than you should get something like the
> > > > > > following:
>
> > > > > > Detected attempt to establish Parent2(3) as the parent of 
> > > > > > Parent1(1)/
> > > > > > Child1(2) but the entity identified by Parent1(1)/Child1(2) is 
> > > > > > already
> > > > > > a child of Parent1(1).  A parent cannot be established or changed 
> > > > > > once
> > > > > > an object has been persisted.
> > > > > > org.datanucleus.exceptions.NucleusUserException: Detected attempt to
> > > > > > establish Parent2(3) as the parent of Parent1(1)/Child1(2) but the
> > > > > > entity identified by Parent1(1)/Child1(2) is already a child of 
> > > > > > Parent1
> > > > > > (1).  A parent cannot be established or changed once an object has
> > > > > > been persisted.
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastoreRelationFieldManager.checkForParen­tSwitch
> > > > > > (DatastoreRelationFieldManager.java:214)
> > > > > >         at 
> > > > > > org.datanucleus.store.appengine.DatastoreRelationFieldManager
> > > > > > $1.setObjectViaMapping(DatastoreRelationFieldManager.java:129)
> > > > > >         at 
> > > > > > org.datanucleus.store.appengine.DatastoreRelationFieldManager
> > > > > > $1.apply(DatastoreRelationFieldManager.java:108)
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelation­s
> > > > > > (DatastoreRelationFieldManager.java:80)
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations
> > > > > > (DatastoreFieldManager.java:795)
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastorePersistenceHandler.insertPostProce­ss
> > > > > > (DatastorePersistenceHandler.java:288)
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObjects
> > > > > > (DatastorePersistenceHandler.java:241)
> > > > > >         at
> > > > > > org.datanucleus.store.appengine.DatastorePersistenceHandler.insertObject
> > > > > > (DatastorePersistenceHandler.java:225)
> > > > > >         at 
> > > > > > org.datanucleus.state.JDOStateManagerImpl.internalMakePersistent
> > > > > > (JDOStateManagerImpl.java:3185)
> > > > > >         at org.datanucleus.state.JDOStateManagerImpl.makePersistent
> > > > > > (JDOStateManagerImpl.java:3161)
> > > > > >         at org.datanucleus.ObjectManagerImpl.persistObjectInternal
> > > > > > (ObjectManagerImpl.java:1298)
> > > > > >         at org.datanucleus.ObjectManagerImpl.persistObject
> > > > > > (ObjectManagerImpl.java:1175)
> > > > > >         at 
> > > > > > org.datanucleus.jdo.JDOPersistenceManager.jdoMakePersistent
> > > > > > (JDOPersistenceManager.java:669)
> > > > > >         at org.datanucleus.jdo.JDOPersistenceManager.makePersistent
> > > > > > (JDOPersistenceManager.java:694)
> > > > > >         at 
> > > > > > hu.mapro.gae.test.forum.TestForum.testMultiParent(TestForum.java:
> > > > > > 44)
> > > > > >         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.internal.runners.TestMethod.invoke(TestMethod.java:59)
> > > > > >         at org.junit.internal.runners.MethodRoadie.runTestMethod
> > > > > > (MethodRoadie.java:98)
> > > > > >        
>
> ...
>
> read more »- Hide quoted text -
>
> - Show quoted text -
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to