如何知道grails事务中发生的异常?

时间:2014-07-16 21:25:34

标签: exception grails transactions

我有一个服务方法,可以在事务中执行某些操作。

public User method1() {
    // some code...
    Vehicle.withTransaction { status ->
        // some collection loop
        // some other delete
        vehicle.delete(failOnError:true)
    }

    if (checkSomething outside transaction) {
        return throw some user defined exception
    }

    return user
}

如果存在运行时异常,我们不必捕获该异常,并且事务将自动回滚。但是如何确定该事务由于某些异常而回滚,并且我想抛出一些用户友好的错误消息。 delete()调用也不会返回任何内容。

如果我通过捕获Exception(超类)在事务中添加try / catch块,它就不会进入该异常块。但我期待它进入该区块并引发用户友好的例外。

编辑1:最好添加try/catch arround withTransaction

任何想法如何解决这个问题?提前谢谢。

1 个答案:

答案 0 :(得分:1)

如果我理解你的问题是正确的,你想知道如何捕获异常,确定异常是什么,并向用户返回一条消息。有几种方法可以做到这一点。我会告诉你我是怎么做的。

在我开始使用代码之前,我可能会提出一些建议。首先,您不需要在服务中显式声明事务(我使用的是v2.2.5)。默认情况下,服务是交易性的(不是什么大不了的事)。

其次,如果在执行服务方法时发生任何异常,事务将自动回滚。

第三,我建议从failOnError:true删除save()(我认为它不适用于delete() ...我可能错了?)。我发现在服务中运行validate()save()更容易,然后将模型实例返回到控制器,在控制器中可以在flash消息中使用对象错误。

以下是我喜欢如何在控制器中使用服务方法和try / catch处理异常和保存的示例:

class FooService {
    def saveFoo(Foo fooInstance) {
        return fooInstance.save()
    }

    def anotherSaveFoo(Foo fooInstance) {
        if(fooInstance.validate()){
            fooInstance.save()
        }else{
            do something else or
            throw new CustomException()
        }

        return fooInstance
    }

}

class FooController {
    def save = {
        def newFoo = new Foo(params)
        try{
            returnedFoo = fooService.saveFoo(newFoo)
        }catch(CustomException | Exception e){
            flash.warning = [message(code: 'foo.validation.error.message',
                    args: [org.apache.commons.lang.exception.ExceptionUtils.getRootCauseMessage(e)],
                    default: "The foo changes did not pass validation.<br/>{0}")]
            redirect('to where ever you need to go')
            return

        }

        if(returnedFoo.hasErrors()){
            def fooErrors = returnedFoo.errors.getAllErrors()

            flash.warning = [message(code: 'foo.validation.error.message',
                    args: [fooErrors],
                    default: "The foo changes did not pass validation.<br/>${fooErrors}")]
            redirect('to where ever you need to go')
            return
        }else {
            flash.success = [message(code: 'foo.saved.successfully.message',
                                default: "The foo was saved successfully")]
            redirect('to where ever you need to go')
        }
    }
}

希望这会有所帮助,或者从更有经验的Grails开发人员那里获得一些其他意见。

我发现以下几种方法可以将异常信息传递给您的用户:

request.exception.cause
request.exception.cause.message
response.status

可能有用的其他相关问题的一些链接:

Exception handling in Grails controllers

Exception handling in Grails controllers with ExceptionMapper in Grails 2.2.4 best practice

https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html