I want multiple users to be able to edit models in a web browser at the same time and conflicts detected when the save (so that the first user to write doesn't have their changes overwritten without the second user explicitly saying so). Here's the example:
User A retrieves object X and is looking at it in their browser.
Then User B retrieves object X, looks at it in their browser, modifies it, and saves it causing a post to the REST api in Grails and a save
on the model to the database.
Then User A modifies and saves the object.
I want the application to detect that object X has been modified since user A retrieved it and I'll display a suitable message to user A with some options.
How do I know if the model has changed? Note that isDirty
will not work and save(flush:true)
will not work.
UPDATE
I see a couple answers that talk about Optimistic Locking and detecting a model change since it was submitted. I want to detect a change since it was retrieved by the user. Please read the question again.
Here I will clarify why Optimistic Locking will not solve the problem described above. However, I can imagine that there may be a way for me to use Optimistic Locking, but as it is described in the answers below and as it is described in the documentation, it will not help. Here's why.
Optimistic Locking works within the request, not across requests. If a second user updates an object while an update request is in progress from the first user, then optimistic locking will only allow one user to perform the update. Optimistic Locking protects against a read-modify-write being interleaved with another read-modify-write in the same request. Here's a time line (where time is top to bottom) of the events that optimistic locking protects against:
User 1 User 2
presses submit presses submit
in update action
| read model
| in update action
| | read model
| | modify model
| | write model
| return
| modify model
| write model - FAILS
return error or something
Writing the model by the first users post fails because the optimistic locking check detects the record was modified since it was read.
What I would like to protect against is the following timeline:
User 1 User 2
visits web app visits web app
clicks link to edit model clicks link to edit model
in edit action
| read model
| render model
return
in edit action
| read model
| render model
return
user edits model user edits model
user thinks... hmm... user submits
in update action
| read model
| modify model from params
| write model
return
user submits
in update action
| read model
| modify model from params
| write model - OOPS! overwrote previous changes
return
From this example you can see that User 1 overwrites User 2's changes. But User 1 made her changes based on an old copy of the model from the database and perhaps would have done something different if she had seen User 2's changes that happened while she was thinking.