I have a simple JDO test cases that consistently reproduces the problem: 1. two app engine tasks modify the same entity at about the same time 2. the tasks use a JDO transaction and use getObjectById to load the entity 3. have task A modify attribute A on the entity (assume A runs first) 4. have task B modify attribute B on the entity
The problem arises when each of the two tasks executes on two different app engine instances. In which case, I can see log messages that say task A has properly set attribute A to a non-null value and the transaction committed successfully. Then when task B runs on a separate instance it prints out that it does not see the changes that were made to attribute A by task A. Then task B logs that it has set attribute B to a non-null value and that its transaction completes successfully.
Then, when I look in the datastore, attribute A is still null even though I can see log output that says it was set to non-null and the transaction was successful. I would have expected one of two things: 1) when task B loads the entity the value of attribute A reflects that it has been set to a non-null value, or 2) task B loads stale data, but the commit fails with a "too much contention" error. Either of those would be fine. (Note that occasionally I do see contention errors)
What am I missing? It seems like there's some weird caching going on each instance. I was pretty sure that loading an entity by its key within a transaction should reflect changes made to that entity even when those changes are made on a separate app engine instance. When writing a test case to reproduce this I created completely new entity classes and tasks to ensure no other code was somehow mucking things up and I reproduced it in production (the devserver gives slightly different behavior).
Any help is greatly appreciated!
Seems like you are having a version issue. Use @version this will automatically handle concurrent modification and will throw an optimistic lock exception.