Thanks for the reply James,
No, I can't do the read and the write in the same tx because I am
doing a non-id based query on a different entity group in between my
read and my write.  But I think I've resolved the issue.

It seems that when I don't do the detatch the issue is gone and the
OPT_VERSION variable actually gets updated.  The trick is that I
needed to use the PersistenceManager for all operations.  I've read
that it's faster to have a dedicated "read only" PersistenceManager,
so I was doing all reads through the same pm and various writes
through newly created pm's.  I just added a ServletContextListener, in
it I setup the pm when a request comes in, and tear it down after the
request is dispatched.  That seems to be working like a charm.

Hope this helps anyone finding themselves in the same boat.

Thanks!!
-bryce



On Fri, Sep 3, 2010 at 6:32 AM, James <[email protected]> wrote:
> Have you tried querying and saving within the same transaction,
> instead of separately?
>
> On Sep 2, 3:36 am, bcottam <[email protected]> wrote:
>> I'm trying to find out if I'm using the @Version annotation properly
>> in my project.
>> I read the "code snippets that work" from Max 
>> Ross:http://gae-java-persistence.blogspot.com/2009/10/optimistic-locking-w...
>> ...but perhaps there's a subtle detail I'm missing.
>>
>> I have a class that gets frequent updates, and I query that class an
>> aweful lot (around 2-3 times per second, and yes: that is critical to
>> the application).
>>
>> The issue I'm seeing is that when I query this object for an update, I
>> often get an outdated version, even though I've got the @Version
>> annotation on the class level.
>>
>> I've not been able to duplicate the issue locally, however, I do see
>> it when I deploy my app.
>> I notice that the OPT_VERSION property in the datastore never seems to
>> change from "1".  Also, I notice that (occasionally, but repeatably)
>> the value of the bean that I read (for update checking) is a few
>> versions behind what it should be.  I can see this by executing a few
>> updates on a bean (sequentially, in different requests), and just
>> monitor the status of the bean (on 1 second intervals) in a different
>> browser.  To see the status, I just have a GWT page that sends a
>> request every second asking for the status of a given bean.  The issue
>> is visible via logging on the server side, so I know it's not just a
>> GWT async request getting lost and eventually finding it's way back to
>> me.
>>
>> Here is a simplified version of the class:
>>
>> @Version(strategy=VersionStrategy.VERSION_NUMBER)
>> @PersistenceCapable(identityType=IdentityType.APPLICATION)
>> public class Product extends BaseBean {
>>
>>     �...@primarykey
>>     �...@persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
>>      Key id;
>>
>>     �...@persistent
>>      BigDecimal currentPrice;
>>
>>     �...@persistent
>>      Date bidStartDate;
>>
>>     �...@persistent
>>      Date bidEndDate;
>>
>>      .... getters/setters
>>
>> }
>>
>> it's super class is BaseBean, it's just there to implement some
>> interfaces and provide a baseline equals implementation:
>> public abstract class BaseBean implements IsSerializable,
>> Serializable, Identifiable {
>>    ...
>>     public boolean equals(Object obj) {...}
>>     ....
>>
>> }
>>
>> here is the method that I'm using to query/update the bean:
>>
>> public Product getUpdatedProduct(Key productId) {
>>      return readObject(Product.class, productId);
>>
>> }
>>
>> public void placeBid(Key productId, BigDecimal bidAmount) {
>>      //read object uses a dedicated PersistenceManager for reads
>>      Product product = readObject(Product.class, productId);
>>      BigDecimal oldPrice = product.getCurrentPrice();
>>
>>      // update the price
>>      product.setCurrentPrice(oldPrice.add(bidAmount));
>>
>>      // saves use a fresh PersistenceManager, so you have to detach or
>> you'll get an exception
>>      product = detatchCopy(product);
>>
>>      saveObject(product);
>>
>> }
>>
>> public <T> T saveObject(T bean) {
>>       PersistenceManager pm = PMF.get();
>>       Transaction tx = pm.currentTransaction();
>>
>>       try {
>>             tx.begin();
>>             bean = pm.makePersistent(bean);
>>             tx.commit();
>>      }
>>      catch(Exception e) {
>>            e.printStackTrace();
>>      }
>>      finally {
>>           wrapUpTransactionIfNeeded(pm, tx);
>>      }
>>
>>      return bean;
>>
>> }
>>
>> I'll be happy to provide more details if needed, I'm sure I'm missing
>> something silly, I just don't know what it is.
>>
>> Thanks in advance,
>> -bryce
>
> --
> 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.
>
>

-- 
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.

Reply via email to