Controller Logic:
def updateObject() {
Object o = Object.get(params.id as Long)
o.otherObjects.clear()
objectDataService.saveObject(o.id)
OtherObject newObject = new OtherObject;
o.addToOtherObjects(newObject)
objectDataService.saveObject(o.id)
}
ServiceLogic
def saveObject(long profileId) {
o.save(flush:true)
}
what happens
in 90% of the cases this will just work.
problems
ERROR errors.GrailsExceptionResolver - StaleObjectStateException occurred when processing request: [GET] /controller/updateObject - parameters:
stuff[]: data
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1].
Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.path.Object#1]
i have read through related questions and found the merge
call you see above. it solved about 50% of the cases but not all.
For us a few different approaches finally solved the StaleObjectException from occuring regularly:
object = object.refresh()
refreshing objects after retrieving them solved most of our StaleObjectExceptions. Especially in cases where there was a possibility that someone would have worked on the same object from somewhere else and changed some of its members (most problems arrived with collection members).
Overall Project stability:
wrongly linked resources
we had a 404 on a specific resource file we did not actually need and therefore ignored it for some time. turns out that the missing file would cause the session to be kept open - thus fabricating StaleObjects left and right.
Therefore as a hint to anyone facing more than the usual (some StaleObjects might always occur - see above answers) StaleObjectExceptions: Make sure that all resources are linked correctly and your developer tools (Chrome F12) do not report any missing files.