Search code examples
grailsexceptiongrails-orm

How to handle GORM exceptions


I'm trying to implement exception handling for Optimistic lock type exceptions that are thrown by Hibernate but I've encountered a strange issue. It seems I'm unable to catch any Gorm exceptions.

For example I have this code in my service:

try {
  User user = User.get(1);
  Thread.sleep(10000);
  user.viewedAt(new Date());
  user.save(flush:true);
} catch (OptimisticLockingException ex) {
  log.error("Optimistic lock exception");
} catch (StaleObjectStateException ex) {
  log.error("Optimistic lock exception");
}

When I hit this block with two threads, it blows up and the exception propagates to Grails' standard exception handler. The catch blocks are never invoked even though the reported exception is StaleObjectStateException.

I've noticed that I can catch the exception if I let it propagate to the controller and catch it there, but it seems I can't implement exception handling in the service which is weird.

What am I missing?


Solution

  • I got to the bottom of this and I'm posting it in case anyone else runs into this. The issue occurred because the try/catch block was in a transactional service. Although grails reported that the exception was thrown during the save() call, in reality it was called AFTER the entire method, when the transaction was committed.

    So it seems that:

    1. flush: true has no effect on transactional services
    2. It's not possible to catch GORM related exceptions in transactional services, at least not without some work

    I finally worked around this by manually managing the transaction myself i.e.

    try {
      User.withNewTransaction {
        User user = User.get(id); // Must reload object
        .. // do stuff
        user.save(flush:true)
      }
    } catch (OptimisticLockingException ex) {
      ...
    }
    

    I hope this is of use to someone else!