I posted the question on Stackoverflow and the consensus is that it should be wrapped in a transaction. http://stackoverflow.com/questions/3782296/java-google-appengine-sharded-counters-without-transactions
I also opened an Appengine issue (is this the right way to report issues in documentation?): http://code.google.com/p/googleappengine/issues/detail?id=3778&q=sharded&colspec=ID%20Type%20Status%20Priority%20Stars%20Owner%20Summary%20Log%20Component On Sep 21, 12:24 pm, Doug Daniels <daniels.doug...@gmail.com> wrote: > I'm going through the Sharded Counters example in > Java:http://code.google.com/appengine/articles/sharding_counters.html > > I have a question about the implementation of the increment method. In > python it explicitly wraps the get() and increment in a transaction. > In the Java example it just retrieves it and sets it. I'm not sure I > fully understand the Datastore and transactions but it seems like the > critical update section should be wrapped in a datastore transaction. > Am I missing something? > > Original code: > public void increment() { > PersistenceManager pm = PMF.get().getPersistenceManager(); > > Random generator = new Random(); > int shardNum = generator.nextInt(NUM_SHARDS); > > try { > Query shardQuery = pm.newQuery(SimpleCounterShard.class); > shardQuery.setFilter("shardNumber == numParam"); > shardQuery.declareParameters("int numParam"); > > List<SimpleCounterShard> shards = > (List<SimpleCounterShard>) shardQuery.execute(shardNum); > SimpleCounterShard shard; > > // If the shard with the passed shard number exists, increment > its count > // by 1. Otherwise, create a new shard object, set its count to > 1, and > // persist it. > if ( > > Transactional code: > > public void increment() { > PersistenceManager pm = PMF.get().getPersistenceManager(); > > Random generator = new Random(); > int shardNum = generator.nextInt(NUM_SHARDS); > > try { > Query shardQuery = pm.newQuery(SimpleCounterShard.class); > shardQuery.setFilter("shardNumber == numParam"); > shardQuery.declareParameters("int numParam"); > > List<SimpleCounterShard> shards = > (List<SimpleCounterShard>) shardQuery.execute(shardNum); > SimpleCounterShard shard; > > // If the shard with the passed shard number exists, increment > its count > // by 1. Otherwise, create a new shard object, set its count to > 1, and > // persist it. > if (shards != null && !shards.isEmpty()) { > Transaction tx = pm.currentTransaction(); > > try { > tx.begin(); > //I believe in a transaction objects need to be > loaded by ID (can't > use the outside queried entity) > Key shardKey = > KeyFactory.Builder(SimpleCounterShard.class.getSimpleName(), > shards.get(0).getID()) > shard = pm.getObjectById(SimpleCounterShard.class, > shardKey); > shard.setCount(shard.getCount() + 1); > tx.commit(); > } finally { > if (tx.isActive()) { > tx.rollback(); > } > } > > } else { > shard = new SimpleCounterShard(); > shard.setShardNumber(shardNum); > shard.setCount(1); > } > > pm.makePersistent(shard); > } finally { > pm.close(); > } > } > > > > > > > > } -- 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=en.