[appengine-java] Re: Sharded Counters in Java not using Transactions?
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 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 shards = > (List) 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 shards = > (List) 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.
[appengine-java] Sharded Counters in Java not using Transactions?
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 shards = (List) 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 shards = (List) 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.
[appengine-java] Re: Use BlobstoreService and ImageService to upload/serve images drawn from an HTML5 canvas Paintweb JS Library
Is it possible or even a good idea to use the Appengine URL Fetch service and forward the image blob upload to the Blobstorage "createUploadURL()" from the server side. http://code.google.com/appengine/docs/java/urlfetch/usingjavanet.html It seems like it could be possible, but not sure it would save me resources in the long run (the images are simple small drawings that could be viewed many many more times than the upload time so I feel like I'd get benefit storing/serving from the BlobstoreService. On Sep 19, 3:02 pm, Doug Daniels wrote: > I'm working on an Appengine application in Java that allows users to > upload images drawn through an HTML5 canvas library called PaintWeb > (http://code.google.com/p/paintweb/). > > Currently I have a servlet that receives the XMLHttpRequest POST from > the paintweb javascript library as a formencoded image. > > 1. Paintweb.js library sends XMLHttpRequest POST > send = 'dataURL=' + encodeURIComponent(ev.dataURL), > headers = {'Content-Type': 'application/x-www-form- > urlencoded'}; > > 2. A custom servlet decodes the form encoded image data as a blob and > stores that in the Datastore with an associated Drawing entity > > 3 Custom servlet serves the Blob's in the datastore as > ContentType("image/png") > > I'm curious if I can use the new BlobstoreService and ImageService > features to upload my HTML5 canvas images and serve them as pure Blobs > (as shown in this > tutorialhttp://ikaisays.com/2010/09/08/gwt-blobstore-the-new-high-performance...) > > According to the documentation (http://code.google.com/appengine/docs/ > java/blobstore/overview.html#Uploading_a_Blob) it seems like the major > stopping point is that I need to POST a form with: > > > Which I don't think is possible from Paintweb. > > Possibly a work around would be if there was some way on the server > side to store a blob in the Blobstorage (instead of the datastore) so > that you could reap the benefits of not using your CPU quota to serve > images. -- 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.
[appengine-java] Use BlobstoreService and ImageService to upload/serve images drawn from an HTML5 canvas Paintweb JS Library
I'm working on an Appengine application in Java that allows users to upload images drawn through an HTML5 canvas library called PaintWeb (http://code.google.com/p/paintweb/). Currently I have a servlet that receives the XMLHttpRequest POST from the paintweb javascript library as a formencoded image. 1. Paintweb.js library sends XMLHttpRequest POST send = 'dataURL=' + encodeURIComponent(ev.dataURL), headers= {'Content-Type': 'application/x-www-form- urlencoded'}; 2. A custom servlet decodes the form encoded image data as a blob and stores that in the Datastore with an associated Drawing entity 3 Custom servlet serves the Blob's in the datastore as ContentType("image/png") I'm curious if I can use the new BlobstoreService and ImageService features to upload my HTML5 canvas images and serve them as pure Blobs (as shown in this tutorial http://ikaisays.com/2010/09/08/gwt-blobstore-the-new-high-performance-image-serving-api-and-cute-dogs-on-office-chairs/) According to the documentation (http://code.google.com/appengine/docs/ java/blobstore/overview.html#Uploading_a_Blob) it seems like the major stopping point is that I need to POST a form with: Which I don't think is possible from Paintweb. Possibly a work around would be if there was some way on the server side to store a blob in the Blobstorage (instead of the datastore) so that you could reap the benefits of not using your CPU quota to serve images. -- 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.
[appengine-java] Datastore and Polymorphic support getObjectByID(Parent.class, childKey)
I'm trying to model a polymorphic relationship in JDO, List where each GameRound could be either a TextRound or PictureRound. I've followed the documentation and modeled the association as a List as described: http://code.google.com/appengine/docs/java/datastore/relationships.html#Polymorphic_Relationships // ... imports ... @PersistenceCapable public class Chef { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private Key favoriteRecipe; } Here is my Game object: @PersistenceCapable public class Game { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; @Persistent private List rounds = new ArrayList(); ... } @PersistenceCapable @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE) public class GameRound { ... } @PersistenceCapable public class SentenceRound extends GameRound { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; ... } @PersistenceCapable public class PictureRound extends GameRound { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; ... } The trouble is in my Game object I iterate through the rounds and try to do a persistenceManager.getObjectById(GameRound.class, key) and I get the following exception: WARNING: /viewGames.jsp javax.jdo.JDOFatalUserException: Exception converting SentenceRound(7) to an internal key. at org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManager.getObjectById(DatastoreJDOPersistenceManager.java: 68) at org.apache.jsp.viewGames_jsp._jspService(viewGames_jsp.java:121) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:94) What's the proper way to retrieve a polymorphic key relationship (for example how would you do it in the Appengine Chef example?). My only other option is to model the relationship as mutually exclusive properties of the GameRound (and manage that in my application logic). @PersistenceCapable @Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE) public class GameRound { @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) private Key key; //Model relationships as optional components because JDO and Appengine don't support //Polymorphic relationships well. @Persistent private SentenceRound sentenceRound; @Persistent private PictureRound pictureRound; ... } -- 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.