StaleObjectStateException when saving/updating an Entity

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

StaleObjectStateException when saving/updating an Entity

Matthias Wenz
Hi there,

I'm having serious trouble with the StaleObjectStateException/optimistic locking when I'm saving multiple different instances of the same Entity.

Here's the relevant part of my model:

A Project has many instances of Sequence which itself may have many Element instances.
When I change an Element instance I want the parent Project instance to be notified in such way that a property contains the latest update date.
The app provides an API so multiple saves of different Element instances occur often.

Right now I'm doing it like this in my ElementAPIController:

def save() {
       Element elementInstance = Element.get(params.id.toLong())
       Sequence sequence = elementInstance.sequence

           Element.withTransaction { status ->

                // assign the new values, nothing special...

               elementInstance.save(flush: true)
           }
           Project.withTransaction { status ->

               Date now = new Date()
               sequence.project.updated = now

               elementInstance.sequence.project.save(flush: true)


               forward action:'show', id:elementInstance.id
           }
}

When I call this only once everything's fine. But when the same API client saves some items very fast, I get the following exception:

Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Project#2]. Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Project#2]
  Line | Method
->> 216 | doCall          in ElementAPIController$_save_closure5$$ENlYV9qq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   573 | withTransaction in org.grails.datastore.gorm.GormStaticApi
|   203 | save . . . . .  in ElementAPIController$$ENlYV9qq
|   886 | runTask         in java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run . . . . . . in     ''
^   680 | run             in java.lang.Thread

What can I do about this? The User Guide only gives very simple information about optimistic locking and exceptions with that - I tried pessimistic locking using like

elementInstance.sequence.project.lock()

but it doesn't work at all. I've searched all the forums, all the usual tips and tricks did not help...

Maybe it would be worth noting that my controller is singleton-scoped, does that change everything in the behavior of the Hibernate session? In my tests prototype-scoping it did not help.

Thanks in advance,
Mat

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: StaleObjectStateException when saving/updating an Entity

burtbeckwith
If you expect concurrent edits then optimistic locking doesn't make sense, so explicit locking is the way to go. Are you locking inside a transaction?

You should consider moving this logic to transactional service methods rather than polluting controllers with persistence logic.

Burt

Matthias Wenz wrote
Hi there,

I'm having serious trouble with the StaleObjectStateException/optimistic locking when I'm saving multiple different instances of the same Entity.

Here's the relevant part of my model:

A Project has many instances of Sequence which itself may have many Element instances.
When I change an Element instance I want the parent Project instance to be notified in such way that a property contains the latest update date.
The app provides an API so multiple saves of different Element instances occur often.

Right now I'm doing it like this in my ElementAPIController:

def save() {
       Element elementInstance = Element.get(params.id.toLong())
       Sequence sequence = elementInstance.sequence

           Element.withTransaction { status ->

                // assign the new values, nothing special...

               elementInstance.save(flush: true)
           }
           Project.withTransaction { status ->

               Date now = new Date()
               sequence.project.updated = now

               elementInstance.sequence.project.save(flush: true)


               forward action:'show', id:elementInstance.id
           }
}

When I call this only once everything's fine. But when the same API client saves some items very fast, I get the following exception:

Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Project#2]. Stacktrace follows:
Message: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Project#2]
  Line | Method
->> 216 | doCall          in ElementAPIController$_save_closure5$$ENlYV9qq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   573 | withTransaction in org.grails.datastore.gorm.GormStaticApi
|   203 | save . . . . .  in ElementAPIController$$ENlYV9qq
|   886 | runTask         in java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run . . . . . . in     ''
^   680 | run             in java.lang.Thread

What can I do about this? The User Guide only gives very simple information about optimistic locking and exceptions with that - I tried pessimistic locking using like

elementInstance.sequence.project.lock()

but it doesn't work at all. I've searched all the forums, all the usual tips and tricks did not help...

Maybe it would be worth noting that my controller is singleton-scoped, does that change everything in the behavior of the Hibernate session? In my tests prototype-scoping it did not help.

Thanks in advance,
Mat

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email
Reply | Threaded
Open this post in threaded view
|

Re: StaleObjectStateException when saving/updating an Entity

Matthias Wenz
Thanks Burt for your quick reply!

I thought that pessimistic locking would be part of the solution, here's how I did it (with no effect whatsoever):

Project.withTransaction { status ->
              elementInstance.sequence.project.lock()
              Date now = new Date()
              sequence.project.updated = now

              
              elementInstance.sequence.project.save(flush: true)


              forward action:'show', id:elementInstance.id
          }

I also tried locking without a transaction - to me the User Guide is not totally clear when transactions are preferable in that cases - also no effect - I still get the exception for optimistic locking.

I know I should move those over to a service, but for what its worth it does not make any difference for my current problem, does it?

Thanks
Mat

Am 11.10.2012 um 19:03 schrieb burtbeckwith <[hidden email]>:

If you expect concurrent edits then optimistic locking doesn't make sense, so
explicit locking is the way to go. Are you locking inside a transaction?

You should consider moving this logic to transactional service methods
rather than polluting controllers with persistence logic.

Burt


Matthias Wenz wrote
Hi there,

I'm having serious trouble with the StaleObjectStateException/optimistic
locking when I'm saving multiple different instances of the same Entity.

Here's the relevant part of my model:

A Project has many instances of Sequence which itself may have many
Element instances.
When I change an Element instance I want the parent Project instance to be
notified in such way that a property contains the latest update date.
The app provides an API so multiple saves of different Element instances
occur often.

Right now I'm doing it like this in my ElementAPIController:

def save() {
      Element elementInstance = Element.get(params.id.toLong())
      Sequence sequence = elementInstance.sequence

          Element.withTransaction { status ->

// assign the new values, nothing special...

              elementInstance.save(flush: true)
          }
          Project.withTransaction { status ->

              Date now = new Date()
              sequence.project.updated = now

              elementInstance.sequence.project.save(flush: true)


              forward action:'show', id:elementInstance.id
          }
}

When I call this only once everything's fine. But when the same API client
saves some items very fast, I get the following exception:

Row was updated or deleted by another transaction (or unsaved-value
mapping was incorrect): [Project#2]. Stacktrace follows:
Message: Row was updated or deleted by another transaction (or
unsaved-value mapping was incorrect): [Project#2]
 Line | Method
->> 216 | doCall          in ElementAPIController$_save_closure5$$ENlYV9qq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   573 | withTransaction in org.grails.datastore.gorm.GormStaticApi
|   203 | save . . . . .  in ElementAPIController$$ENlYV9qq
|   886 | runTask         in
java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run . . . . . . in     ''
^   680 | run             in java.lang.Thread

What can I do about this? The User Guide only gives very simple
information about optimistic locking and exceptions with that - I tried
pessimistic locking using like

elementInstance.sequence.project.lock()

but it doesn't work at all. I've searched all the forums, all the usual
tips and tricks did not help...

Maybe it would be worth noting that my controller is singleton-scoped,
does that change everything in the behavior of the Hibernate session? In
my tests prototype-scoping it did not help.

Thanks in advance,
Mat

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email





--
View this message in context: http://grails.1312388.n4.nabble.com/StaleObjectStateException-when-saving-updating-an-Entity-tp4636381p4636382.html
Sent from the Grails - user mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: StaleObjectStateException when saving/updating an Entity

Matthias Wenz
Following up on this:

I also moved the complete persistence logic to a transactional service which made no difference. I tried pessimistic locking in all ways I expect it to work - it didn't.

What I finally did to move on was to remove the need for updating the project's updated-date in-place. Now my frontend performs all saves (here we don't need pessimistic locking) and finally calls a web service which sets a new updated-date on the corresponding project.
That breaks most rules I learned about separation of concerns but it's the only possible way since GORM doesn't seem to work as expected/proposed for me.

-- Mat

Am 12.10.2012 um 10:55 schrieb Matthias Wenz <[hidden email]>:

Thanks Burt for your quick reply!

I thought that pessimistic locking would be part of the solution, here's how I did it (with no effect whatsoever):

Project.withTransaction { status ->
              elementInstance.sequence.project.lock()
              Date now = new Date()
              sequence.project.updated = now

              
              elementInstance.sequence.project.save(flush: true)


              forward action:'show', id:elementInstance.id
          }

I also tried locking without a transaction - to me the User Guide is not totally clear when transactions are preferable in that cases - also no effect - I still get the exception for optimistic locking.

I know I should move those over to a service, but for what its worth it does not make any difference for my current problem, does it?

Thanks
Mat

Am 11.10.2012 um 19:03 schrieb burtbeckwith <[hidden email]>:

If you expect concurrent edits then optimistic locking doesn't make sense, so
explicit locking is the way to go. Are you locking inside a transaction?

You should consider moving this logic to transactional service methods
rather than polluting controllers with persistence logic.

Burt


Matthias Wenz wrote
Hi there,

I'm having serious trouble with the StaleObjectStateException/optimistic
locking when I'm saving multiple different instances of the same Entity.

Here's the relevant part of my model:

A Project has many instances of Sequence which itself may have many
Element instances.
When I change an Element instance I want the parent Project instance to be
notified in such way that a property contains the latest update date.
The app provides an API so multiple saves of different Element instances
occur often.

Right now I'm doing it like this in my ElementAPIController:

def save() {
      Element elementInstance = Element.get(params.id.toLong())
      Sequence sequence = elementInstance.sequence

          Element.withTransaction { status ->

// assign the new values, nothing special...

              elementInstance.save(flush: true)
          }
          Project.withTransaction { status ->

              Date now = new Date()
              sequence.project.updated = now

              elementInstance.sequence.project.save(flush: true)


              forward action:'show', id:elementInstance.id
          }
}

When I call this only once everything's fine. But when the same API client
saves some items very fast, I get the following exception:

Row was updated or deleted by another transaction (or unsaved-value
mapping was incorrect): [Project#2]. Stacktrace follows:
Message: Row was updated or deleted by another transaction (or
unsaved-value mapping was incorrect): [Project#2]
 Line | Method
->> 216 | doCall          in ElementAPIController$_save_closure5$$ENlYV9qq
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|   573 | withTransaction in org.grails.datastore.gorm.GormStaticApi
|   203 | save . . . . .  in ElementAPIController$$ENlYV9qq
|   886 | runTask         in
java.util.concurrent.ThreadPoolExecutor$Worker
|   908 | run . . . . . . in     ''
^   680 | run             in java.lang.Thread

What can I do about this? The User Guide only gives very simple
information about optimistic locking and exceptions with that - I tried
pessimistic locking using like

elementInstance.sequence.project.lock()

but it doesn't work at all. I've searched all the forums, all the usual
tips and tricks did not help...

Maybe it would be worth noting that my controller is singleton-scoped,
does that change everything in the behavior of the Hibernate session? In
my tests prototype-scoping it did not help.

Thanks in advance,
Mat

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email





--
View this message in context: http://grails.1312388.n4.nabble.com/StaleObjectStateException-when-saving-updating-an-Entity-tp4636381p4636382.html
Sent from the Grails - user mailing list archive at Nabble.com.

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

   http://xircles.codehaus.org/manage_email




Reply | Threaded
Open this post in threaded view
|

Re: StaleObjectStateException when saving/updating an Entity

littlej
In reply to this post by Matthias Wenz
If its any consolation, I am getting the same error if I try to update a single value in a domain object, even if I put the code to read, update and save it in a service with @Transactional at the top.

It seems there is no working way to do simple locking to allow two users to update the same object at the same time.

My only solution is to remove functionality, at great detriment to the project, until someone can provide a way to do simple locking which doesnt generate this error in grails.

My service which fails:

domain object:

    class Query {
      String sql
      String name
      int counter
    }

service:
    @Transactional
    class aService {

    def count(Query query) {
    Query q2 = Query.get(query.id)
    q2.counter++
    q2.save();
    }