0

I am trying to implement a basic optimistic lock mechanism with a retry interceptor.

So the thing is there is a object Quiz with a property responsesCount. In case that there is a optimistic Lock exception thrown during an update of the quiz, the respective update method will be invoked again from the retry interceptor.

The thing is that something is not right because the retried method has the same version number number every time, and because of this it will fail the transaction no matter what.

version: 10

process A: start update quiz, version 10 process B: start update quiz, version 10 process B: finish update quiz, version 11 process A: optimistic exception thrown raised update quiz, retry process A inside the retried method the version is always 10

What can I do then? It should increment automatically the version in order to success the transaction

Qfeast Quizzes
  • 145
  • 2
  • 12

3 Answers3

1

It seems to me that you want to update the quizz, even if someone else has updated it behind your back (which throws the optimistic exception). If that's the case, why do you enable optimistic logking on this entity? Just remove the version field, and it will work without even retrying.

If you really want to keep the version field, then change the method so that it gets the quizz from DB, copies the version number of the freshly loaded quizz to your detached instance, and then merge the detached instance to copy all the new values to the attached one.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • The reason why I am thinking to use the optimistic locking is to prevent for example the cases where many concurrent users are taking a quiz and increment in the same time the quizResponsesCount property of the quiz. Right now I am experimenting what you suggested: I modified my service layer in the way that it retrieves only fresh objects (quizzes) from db and then updates them . As far as I tested, it seams that the retry mechanism works well in this way, meaning it detects optimistic locking and then retries the method and will it succeed next time. Is it ok like this? – Qfeast Quizzes Mar 01 '11 at 18:08
1

An optimistic lock exception is handled like this:

First re-read the record, getting the new version number and the updated field values which the conflicting transaction wrote.

Then reapply your operation, based on the new values. In your case this is simple -- incrementing a value is order-independent or commutative. Other operations might not be simple to reapply -- for example, suppose the transactions were both trying to move a bug in an issue tracker from one workflow state to another. This transition can only happen once, so the retrying transaction would need to check that the bug was still in a valid state for that transition, and if not it would report an error to the user.

tgdavies
  • 10,307
  • 4
  • 35
  • 40
0

You're trying to defeat the optimistic lock :D, which raises the question: do you need the optimistic lock?

The only sane way I can see of retrying, without loosing previous data, is to refresh the object and then apply the changes again... in any way, you're going to override data, which goes against the idea of optimistic locks.

In your case, I would either disable optimistic locking at all, or put the count in an ancillary table, without optimistic locking.

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • The count does need to be locked -- otherwise two clients may read '1', and then both write '2' when the correct count is '3'. – tgdavies Mar 01 '11 at 21:35