Several people <http://bit.ly/xSj2ef> have detected a strange behaviour in Google App Engine JDO, where your app unpredictably returns stale data.
I've written a small servlet to demonstrate this. The code is included in this note, and the app uses the plain vanilla jdoconfig.xml also included here. You can see it live deployed in appengine here <http://bastide07.appspot.com/staledata> When using this app, you will notice that occasionally the records that have just been added or deleted do not show up until a couple of refreshes. Things that have been tried but do not appear to work : - Wrapping transactions around adds and deletes - Using cache control headers in response - setting <property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" /> in jdoconfig.xml I suspect a threading issue that can be solved by configuration options... I must be doing something terribly wrong, but I do not see what... Any help appreciated -- 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/-/3nebSrKk9G4J. 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.
package staledata;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.*;
import javax.jdo.Extent;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.persistence.*;
@Entity
class MyEntity {
@Id
private String key;
public MyEntity(String key) {
super();
this.key = key;
}
public String getKey() {
return key;
}
}
@SuppressWarnings("serial")
public class StaledataServlet extends HttpServlet {
private static final PersistenceManagerFactory pmfInstance = JDOHelper
.getPersistenceManagerFactory("transactions-optional");
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
PrintWriter page = resp.getWriter();
String uri = req.getRequestURI();
resp.setContentType("text/html");
page.print("<body><h1>Stale data in GAE DataStore</H1>");
page.print("<a href=http://bit.ly/xqCKWU>Source code and explanations</a><br>");
page.print("<a href=" + uri +">Refresh</a>");
PersistenceManager pm = pmfInstance.getPersistenceManager();
String message = "no exception detected";
try {
if ("ADD".equals( req.getParameter("action"))) {
MyEntity record = new MyEntity(req.getParameter("key"));
pm.makePersistent(record);
message = "Record saved";
} else if ("DELETE".equals( req.getParameter("action"))) {
MyEntity record = pm.getObjectById(MyEntity.class, req.getParameter("key"));
pm.deletePersistent(record);
message = "Record deleted";
} else {
// Show form
page.print("<h2>Add new record</h2>");
page.print("<form>Key: <input name=key> <input type=submit name=action value=ADD></form>");
// List currently saved entities
Extent<MyEntity> extent = pm.getExtent(MyEntity.class, false);
page.print("<h2>Saved entities :</h2><table border=1><tr><th>Key</th><th>Action</th></tr>");
for (MyEntity record : extent) {
String key = record.getKey();
page.print("<tr><td>" + key + "</td>");
page.print("<td><a href=" + uri +"?action=DELETE&key=" + key +">delete</a></tr>");
}
page.print("</table>");
}
} catch (Exception e) {
message = e.getMessage();
} finally {
pm.close();
}
page.print("<p>" + message +"</p>");
page.print("<a href=" + uri +">Refresh</a></body>");
}
}
jdoconfig.xml
Description: XML document
