Grails withTransaction - why is it on a domain object?

We need to be able to rollback a complex transaction in the service without throwing an exception for the caller. I understand that the only way to achieve this is to use with Transaction.

The question arises:

  • Why do I need to call this on a domain object like Books.withTransaction
  • What if there is no corresponding domain object, which is a consequence of choosing a random one?

Below is more or less what I am trying to do. The use case is to withdraw from an account and put it on a credit card. If the transfer fails, we want to cancel the transaction, but not the payment record log, which should be recorded in a separate transaction (using RequiresNew). In any case, the service method should return a complex object, not an exception.

someService.groovy

Class SomeService {
    @NotTransactional
    SomeComplexObject someMethod() {
        SomeDomainObject.withTransaction{ status ->
            DomainObject ob1 = new DomainObject.save()
            LogDomainObject ob2 = insertAndCommitLogInNewTransaction()
            SomeComplexObject ob3 = someAction()
            if (!ob3.worked) {
                 status.setRollbackOnly() // only rollback ob1, not ob2!
            }
            return ob3
        }
    }
}

      

The above is flawed - I am assuming "return ob3" will not return ob3 from the method as it does in the closure. Not sure how to communicate from within the closure to go beyond it.

+3


source to share


1 answer


Into your main question, you can choose a random domain object if you like, it won't hurt. Or, if you like, you can find the current session and open a transaction instead:

grailsApplication.sessionFactory.currentSession.withTransaction { /* Do the things */ }

      

Stylistically, I have no preference here. Others can.

Not sure how to communicate from inside the closure to the outside.



In general, this can be difficult; withTransaction

can basically return whatever it wants, no matter what its closure argument returns. But it turns out that it withTransaction

returns the value returned by its closure. See here:

groovy> println(MyDomainObject.withTransaction { 2 + 2 })
4

      

By convention, all methods withFoo

that accept a closure should work in such a way that you can do what you are trying to do.

+7


source







All Articles