How do I prevent exceptions from causing a transaction rollback under Grails?

孤人 提交于 2021-02-06 08:49:58

问题


My Grails service is having an issue where a swallowed exception unrelated to a transaction is causing the transaction to rollback even when it is unrelated to the persistance of the domain object.

In my service I have something along the lines of

updateSomething(domainObj) {
    def oldFilename = domainObj.filename
    def newFilename = getNewFilename()

    domainObj.filename = newFilename
    domainObj.save(flush: true)

    try {
        cleanUpOldFile(oldFilename)
    } catch (cleanupException) {
        // oh well, log and swallow
    }
}

What I am seeing is that when I have exception when I am cleaning up the old file, I log it and swallow it, but it still causes the transaction to rollback, even though I am already done updating the domain object.

How do I limit the scope transaction to complete before the clean up or is there another way to get the clean up exception to not cause a rollback?

Just for the record I am using Grails 2.1.1


回答1:


You can use annotations to do more fine-grained transaction demarcation. By default services are transactional, and all public methods are transactional. But if you use any @Transactional annotations, Grails doesn't make everything transactional - you have complete control.

Runtime exceptions automatically trigger rollbacks, but checked exceptions don't. Even though Groovy doesn't required that you catch checked exceptions, the feature is a Spring thing which doesn't know about Groovy exception handling.

Transactions are implemented by wrapping your service class instance in a proxy. If an exception "escapes" the proxy, whether it's then caught or not, the rollback will have already happened.

So you have a few options. Annotate updateSomething as @Transactional but don't annotate cleanUpOldFile:

import org.springframework.transaction.annotation.Transactional

@Transactional
def updateSomething(domainObj) {
...
}

def cleanUpOldFile(...) {
   ...
}

You can also annotate cleanUpOldFile with one or more unchecked exceptions that shouldn't roll back a transaction (or in other use cases checked exceptions that should), e.g.

@Transactional(noRollbackFor=[FooException, BarException])
def cleanUpOldFile(...) {
   ...
}



回答2:


In addition to @Burt Beckwith's answer, if you have a service where you just don't want transactions (which I actually did in my case) you can turn off transactions on all public methods by adding

static transactional = false

to the Service class.



来源:https://stackoverflow.com/questions/15823677/how-do-i-prevent-exceptions-from-causing-a-transaction-rollback-under-grails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!