Saturday, May 01, 2010

Summary on Transaction Rollback in Grails

This post is a summary on how to rollback transactions in grails application, and highlights a stain in grails reference document.

Rollback Programmatic Transactions

In Grails, we can use withTransaction method on domain classes to deal with programmatic transactions. This method takes a closure, which receives a TransactionStatus instance as its first argument. In order to rollback transactions, we can invoke the setRollbackOnly() method on TransactionStatus. Here is an example from grails reference document:
Account.withTransaction { status ->
def source = Account.get(params.from)
def dest = Account.get(params.to)
def amount = params.amount.toInteger()

if(source.active) {
source.balance -= amount
if(dest.active) {
dest.amount += amount
}else {
status.setRollbackOnly()
}
}
}

Rollback Declarative Transactions

With service, it's not a big deal to implement declarative transactions in grails. If you want to rollback, all that you need to do is to throw a RuntimeException or its subclass in service method. The following code shows how to do this job:
class DomainbService {
boolean transactional = true

def service2() {
new B().save()
throw new RuntimeException("save b failed!")
}
}
There is one thing you should notice: grails refernce document doesn't spot the exception you throw in method must be an RuntimeException object. Actually, if you throw an Exception object, the transaction doesn't rollback. You can have a test to verify this. And in spring reference document, you can find that you should throw an "unchecked" exception to trigger a rollback when you are using declarative transaction.