Hi,
I've created a testservlet to illustrate my problem.
I want an owned uni-directional relationship between an entity and a
list of sub entities.
The model enties are detachable because the client shall be a GWT app.
When I add one sub entity it works as expected.
When I add the second only the second entity is stored in the
datastore and the first is lost.
When I add the third sub-entity I get an exception.
Here is the testservlet and then I'll add the result of the three
cases.
What can be wrong?
Gunnar

package com.google.appengine.demo;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class ListordertestServlet extends HttpServlet {

        StringBuilder sb = new StringBuilder();
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
                sb = new StringBuilder();
                resp.setContentType("text/plain");
                deleteAll();
                MyEntity entity = persist();
                add(entity, "one");
                query();
                add(entity, "two");
                query();
//              add(entity, "three");
//              query();
                resp.getWriter().println(sb.toString());
        }

        private MyEntity persist() {
                MyEntity entity = new MyEntity();
                MyEntity detached = null;
                ArrayList<SubEntity> subEntities = new ArrayList<SubEntity>();
                entity.setMyList(subEntities);
                PersistenceManager pm = PMF.get().getPersistenceManager();
                Transaction tx = pm.currentTransaction();
                try {
                        tx.begin();
                        pm.makePersistent(entity);
                        tx.commit();
                        detached = pm.detachCopy(entity);
                        sb.append("persisted entity: " + entity.getId() + "\n");
                        sb.append("detached object: " + detached + "\n");
                } catch (Exception e) {
                        printStackTrace(e);
                } finally {
                        if (tx.isActive())
                                tx.rollback();
                        pm.close();
                }
                return detached;
        }

        private MyEntity add(MyEntity entity, String name) {
                MyEntity detached = null;
                sb.append("before add " + entity.toString() + "\n");
                PersistenceManager pm = PMF.get().getPersistenceManager();
                Transaction tx = pm.currentTransaction();
                try {
                        tx.begin();
                        final SubEntity subEntity = new SubEntity(name);
                        entity.getMyList().add(subEntity);
                        pm.makePersistent(entity);
                        tx.commit();
                        detached = pm.detachCopy(entity);
                        sb.append("added sub-entity " + name + "\n");
                        sb.append("detached object: " + detached + "\n");
                } catch (Exception e) {
                        printStackTrace(e);
                } finally {
                        if (tx.isActive())
                                tx.rollback();
                        pm.close();
                }
                return detached;
        }

        private void deleteAll() {
                PersistenceManager pm = PMF.get().getPersistenceManager();
                Query query = pm.newQuery(MyEntity.class);
                Transaction tx = pm.currentTransaction();
                try {
                        tx.begin();
                        List<MyEntity> results = (List<MyEntity>) 
query.execute();
                        if (results.iterator().hasNext()) {
                                pm.deletePersistentAll(results);
                        }
                        tx.commit();
                        sb.append("deleted all objects" + "\n");
                } catch (Exception e) {
                        printStackTrace(e);
                } finally {
                        if (tx.isActive())
                                tx.rollback();
                        query.closeAll();
                        pm.close();
                }
        }

        private void query() {
                sb.append("query\n");
                PersistenceManager pm = PMF.get().getPersistenceManager();
                Query query = pm.newQuery(MyEntity.class);
                try {
                        List<MyEntity> results = (List<MyEntity>) 
query.execute();
                        if (results.iterator().hasNext()) {
                                for (MyEntity e : results) {
                                        sb.append(e + "\n");
                                        for (SubEntity s : e.getMyList()) {
                                                sb.append(s + "\n");
                                        }
                                        sb.append("-------------\n");
                                }
                        }
                } catch (Exception e) {
                        printStackTrace(e);
                } finally {
                        query.closeAll();
                        pm.close();
                }

        }

        private void printStackTrace(Exception e) {
                final ByteArrayOutputStream ba = new ByteArrayOutputStream();
                PrintStream ps = new PrintStream(ba);
                e.printStackTrace(ps);
                sb.append(ba.toString());
                e.printStackTrace();
        }

}


Test with one subentity:
deleted all objects
persisted entity: 54
detached object: MyEntity [keyId=54, myList=[]]
before add MyEntity [keyId=54, myList=[]]
added sub-entity one
detached object: MyEntity [keyId=54, myList=[SubEntity [name=one,
id=55]]]
query
MyEntity [keyId=54, myList=[SubEntity [name=one, id=55]]]
SubEntity [name=one, id=55]
-------------


Test with two subentities:
deleted all objects
persisted entity: 56
detached object: MyEntity [keyId=56, myList=[]]
before add MyEntity [keyId=56, myList=[]]
added sub-entity one
detached object: MyEntity [keyId=56, myList=[SubEntity [name=one,
id=57]]]
query
MyEntity [keyId=56, myList=[SubEntity [name=one, id=57]]]
SubEntity [name=one, id=57]
-------------
before add MyEntity [keyId=56, myList=[SubEntity [name=one, id=57]]]
added sub-entity two
detached object: MyEntity [keyId=56, myList=[SubEntity [name=one,
id=57], SubEntity [name=two, id=58]]]
query
MyEntity [keyId=56, myList=[SubEntity [name=two, id=58]]]
SubEntity [name=two, id=58]
-------------


Test with three subentities:
deleted all objects
persisted entity: 59
detached object: MyEntity [keyId=59, myList=[]]
before add MyEntity [keyId=59, myList=[]]
added sub-entity one
detached object: MyEntity [keyId=59, myList=[SubEntity [name=one,
id=60]]]
query
MyEntity [keyId=59, myList=[SubEntity [name=one, id=60]]]
SubEntity [name=one, id=60]
-------------
before add MyEntity [keyId=59, myList=[SubEntity [name=one, id=60]]]
added sub-entity two
detached object: MyEntity [keyId=59, myList=[SubEntity [name=one,
id=60], SubEntity [name=two, id=61]]]
query
MyEntity [keyId=59, myList=[SubEntity [name=two, id=61]]]
SubEntity [name=two, id=61]
-------------
before add MyEntity [keyId=59, myList=[SubEntity [name=one, id=60],
SubEntity [name=two, id=61]]]
java.lang.NullPointerException
        at
org.datanucleus.store.appengine.DatastorePersistenceHandler.deleteObject(DatastorePersistenceHandler.java:
562)
        at
org.datanucleus.store.appengine.DatastoreFKListStoreSpecialization.removeAt(DatastoreFKListStoreSpecialization.java:
144)
        at
org.datanucleus.store.mapped.scostore.FKListStore.removeAt(FKListStore.java:
525)
        at
org.datanucleus.store.mapped.scostore.AbstractListStore.remove(AbstractListStore.java:
318)
        at org.datanucleus.sco.backed.ArrayList.remove(ArrayList.java:913)
        at org.datanucleus.sco.SCOListIterator.remove(SCOListIterator.java:
145)
        at
org.datanucleus.sco.SCOUtils.updateListWithListElements(SCOUtils.java:
828)
        at org.datanucleus.sco.simple.ArrayList.attachCopy(ArrayList.java:
231)
        at
org.datanucleus.store.fieldmanager.AttachFieldManager.storeObjectField(AttachFieldManager.java:
205)
        at
org.datanucleus.state.AbstractStateManager.providedObjectField(AbstractStateManager.java:
1037)
        at com.google.appengine.demo.MyEntity.jdoProvideField(MyEntity.java)
        at com.google.appengine.demo.MyEntity.jdoProvideFields(MyEntity.java)
        at
org.datanucleus.state.JDOStateManagerImpl.provideFields(JDOStateManagerImpl.java:
2715)
        at
org.datanucleus.state.JDOStateManagerImpl.internalAttachCopy(JDOStateManagerImpl.java:
4055)
        at
org.datanucleus.state.JDOStateManagerImpl.attachCopy(JDOStateManagerImpl.java:
3987)
        at
org.datanucleus.ObjectManagerImpl.attachObjectCopy(ObjectManagerImpl.java:
1778)
        at
org.datanucleus.ObjectManagerImpl.persistObjectInternal(ObjectManagerImpl.java:
1260)
        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
com.google.appengine.demo.ListordertestServlet.add(ListordertestServlet.java:
67)
        at
com.google.appengine.demo.ListordertestServlet.doGet(ListordertestServlet.java:
29)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:693)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:806)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:
487)
        at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1093)
        at
com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:
51)
        at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1084)
        at
com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:
43)
        at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1084)
        at
com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:
121)
        at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1084)
        at
org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:
360)
        at
org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:
216)
        at
org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:
181)
        at
org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:
712)
        at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:
405)
        at
com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:
70)
        at
org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:
139)
        at com.google.appengine.tools.development.JettyContainerService
$ApiProxyHandler.handle(JettyContainerService.java:352)
        at
org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:
139)
        at org.mortbay.jetty.Server.handle(Server.java:313)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:
506)
        at org.mortbay.jetty.HttpConnection
$RequestHandler.headerComplete(HttpConnection.java:830)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:514)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)
        at
org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:
396)
        at org.mortbay.thread.BoundedThreadPool
$PoolThread.run(BoundedThreadPool.java:442)
query
MyEntity [keyId=59, myList=[SubEntity [name=two, id=61]]]
SubEntity [name=two, id=61]
-------------

-- 
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 [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-java?hl=en.

Reply via email to