I created a JPA @MappedSuperclass containing the Key for all my model objects, so that I could encapsulate the GAE-specific code. (Instead of using Keys directly, inter-component communication is using Long ID's for possible compatibility with other backing stores.)
When I put the Key instance in the superclass instead of the concrete instance, most things work -- except for removing children. Both removing from a Collection and calling em.remove() on the instance results in a NPE from the guts of DataNucleus, though I have not yet been able to try out a RDBMS with standalone DataNucleus JARs to verify the error in other environments. Exception can be seen here: http://entitytest.latest.duh-test.appspot.com/ The sample code to reproduce the issue is available here: http://entitytest.latest.duh-test.appspot.com/src/entitytest/GaeDatum.java http://entitytest.latest.duh-test.appspot.com/src/entitytest/ParentTestEntity.java http://entitytest.latest.duh-test.appspot.com/src/entitytest/ChildTestEntity.java http://entitytest.latest.duh-test.appspot.com/src/entitytest/EntityTestServlet.java Backtrace contents also preserved below (snipped at servlet entry point) for search history: ===== successfully added parent successfully added child; parent now shows 1 java.lang.NullPointerException at org.datanucleus.store.mapped.mapping.PersistenceCapableMapping.getObjectForApplicationIdentity (PersistenceCapableMapping.java:971) at org.datanucleus.store.mapped.mapping.PersistenceCapableMapping.getObject (PersistenceCapableMapping.java:720) at org.datanucleus.store.appengine.DatastoreRelationFieldManager.lookupParent (DatastoreRelationFieldManager.java:309) at org.datanucleus.store.appengine.DatastoreRelationFieldManager.fetchRelationField (DatastoreRelationFieldManager.java:289) at org.datanucleus.store.appengine.DatastoreFieldManager.fetchObjectField (DatastoreFieldManager.java:271) at org.datanucleus.state.AbstractStateManager.replacingObjectField (AbstractStateManager.java:1197) at entitytest.ChildTestEntity.jdoReplaceField(ChildTestEntity.java) at entitytest.ChildTestEntity.jdoReplaceFields(ChildTestEntity.java) at org.datanucleus.state.JDOStateManagerImpl.replaceFields (JDOStateManagerImpl.java:2772) at org.datanucleus.state.JDOStateManagerImpl.replaceFields (JDOStateManagerImpl.java:2791) at org.datanucleus.store.appengine.DatastorePersistenceHandler.fetchObject (DatastorePersistenceHandler.java:443) at org.datanucleus.state.JDOStateManagerImpl.loadSpecifiedFields (JDOStateManagerImpl.java:1519) at org.datanucleus.state.JDOStateManagerImpl.isLoaded (JDOStateManagerImpl.java:1925) at org.datanucleus.jpa.JPAAdapter.isLoaded(JPAAdapter.java:834) at org.datanucleus.store.mapped.mapping.PersistenceCapableMapping.preDelete (PersistenceCapableMapping.java:1132) at org.datanucleus.store.appengine.DependentDeleteRequest.execute (DependentDeleteRequest.java:71) at org.datanucleus.store.appengine.DatastorePersistenceHandler.deleteObject (DatastorePersistenceHandler.java:533) at org.datanucleus.state.JDOStateManagerImpl.internalDeletePersistent (JDOStateManagerImpl.java:4198) at org.datanucleus.state.JDOStateManagerImpl.deletePersistent (JDOStateManagerImpl.java:4166) at org.datanucleus.ObjectManagerImpl.deleteObjectInternal (ObjectManagerImpl.java:1470) at org.datanucleus.store.mapped.scostore.FKListStore.clear (FKListStore.java:585) at org.datanucleus.sco.queued.ClearOperation.perform (ClearOperation.java:39) at org.datanucleus.sco.backed.List.flush(List.java:270) at org.datanucleus.store.mapped.mapping.CollectionMapping.postUpdate (CollectionMapping.java:208) at org.datanucleus.store.appengine.DatastoreRelationFieldManager.runPostUpdateMappingCallbacks (DatastoreRelationFieldManager.java:232) at org.datanucleus.store.appengine.DatastoreRelationFieldManager.access $400(DatastoreRelationFieldManager.java:49) at org.datanucleus.store.appengine.DatastoreRelationFieldManager $1.apply(DatastoreRelationFieldManager.java:114) at org.datanucleus.store.appengine.DatastoreRelationFieldManager.storeRelations (DatastoreRelationFieldManager.java:80) at org.datanucleus.store.appengine.DatastoreFieldManager.storeRelations (DatastoreFieldManager.java:795) at org.datanucleus.store.appengine.DatastorePersistenceHandler.updateObject (DatastorePersistenceHandler.java:494) at org.datanucleus.state.JDOStateManagerImpl.flush (JDOStateManagerImpl.java:4576) at org.datanucleus.ObjectManagerImpl.flushInternal (ObjectManagerImpl.java:2814) at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java: 2754) at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java: 2893) at org.datanucleus.TransactionImpl.internalPreCommit (TransactionImpl.java:369) at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:256) at org.datanucleus.jpa.EntityTransactionImpl.commit (EntityTransactionImpl.java:104) at entitytest.EntityTestServlet.doGet(EntityTestServlet.java:44) -- 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-j...@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=.