[appengine-java] Re: Sharded Counters in Java not using Transactions?

2010-09-24 Thread Doug Daniels
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?

2010-09-21 Thread Doug Daniels
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

2010-09-19 Thread Doug Daniels
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

2010-09-19 Thread Doug Daniels
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)

2010-07-12 Thread Doug Daniels
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.