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.