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.
