StaleObjectStateException while trying to lock domain object
I've recently come across some concurrent modification errors while trying
to add child objects to a list on a parent object.
From what I've read, adding the child objects will bump the version number
on the parent object, and so if another thread is midway through my create
method it'll complain.
Fair enough.
I went back and tried to lock the domain object so it will block until the
previous addition is complete. Surprisingly, it now seems to throw a
StaleObjectStateException when I try and lock the object!
Here's my test code:
def create(User user, Company company, ReferenceCodeCommand cmd) {
log.debug("superbooking type: " +
cmd.superBooking.getClass().getName())
cmd.superBooking.refresh();
log.debug("#" + random + " Locking superbooking: " + superBooking.id)
def superBooking = SuperBooking.lock(cmd.superBooking.id)
log.debug("#" + random + " Superbooking: " + superBooking.id + "
locked")
def referenceCode = new ReferenceCode(cmd.properties)
def random = Math.random()
log.debug("#" + random + " ReferenceCode test point 1. SuperBooking
version " + referenceCode.superBooking.version)
superBooking.addToRefs(referenceCode)
log.debug("#" + random + " ReferenceCode test point 2. SuperBooking
version " + superBooking.version)
if (!referenceCode.hasErrors()
&& referenceCode.save(flush: true)) {
log.debug("ReferenceCode saved successfully")
} else {
log.warn("#" + random + " ReferenceCode not saved successfully
${referenceCode}.")
}
log.debug("#" + random + " ReferenceCode test point 3. SuperBooking
version " + superBooking.version)
superBooking.save(flush: true, failOnError: true)
log.debug("#" + random + " ReferenceCode test point 4. SuperBooking
version " + superBooking.version)
return referenceCode
}
And here's some sample output:
2013-09-06 13:31:21,645 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - superbooking type:
com.ngs.id.model.SuperBooking
2013-09-06 13:31:21,667 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 Locking superbooking:
208535
2013-09-06 13:31:21,667 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 Superbooking: 208535
locked
2013-09-06 13:31:21,667 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 ReferenceCode test
point 1. SuperBooking version 6
2013-09-06 13:31:21,667 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 ReferenceCode test
point 2. SuperBooking version 6
2013-09-06 13:31:21,701 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 ReferenceCode test
point 3. SuperBooking version 7
2013-09-06 13:31:21,708 [http-bio-8080-exec-19] DEBUG
dao.ReferenceCodeDAOService - #0.06947409938388194 ReferenceCode test
point 4. SuperBooking version 7
| Error 2013-09-06 13:31:21,715 [http-bio-8080-exec-20] ERROR
errors.GrailsExceptionResolver - StaleObjectStateException occurred when
processing request: [POST]
/interpreter-direct/api/superBooking/208535/referenceCode/
Row was updated or deleted by another transaction (or unsaved-value
mapping was incorrect): [com.ngs.id.model.SuperBooking#208535]. Stacktrace
follows:
Message: Row was updated or deleted by another transaction (or
unsaved-value mapping was incorrect):
[com.ngs.id.model.SuperBooking#208535]
The error happens on the line where I'm locking the SuperBooking. This is
really confusing to me: from what I've read, lock() will fetch the row
from the DB and lock it until the transaction is complete. I would have
thought that a StaleObjectStateException doesn't even make sense here.
Does anyone have any tips for me, or perhaps an alternate approach? This
has a serious impact on our application.
Thanks!
No comments:
Post a Comment