Gre*_*egg 13 grails exception stripe-payments
在我的Grails服务中,我有如下代码:
def createCharge(chargeParams) {
try {
def charge = Charge.create(chargeParams)
} catch (CardException e) {
throw e
}
}
Run Code Online (Sandbox Code Playgroud)
从我的控制器我执行以下操作:
try {
service.createCharge(chargeParams)
} catch(CardException e) {
}
Run Code Online (Sandbox Code Playgroud)
但是,我的控制器没有捕获重新抛出的CardException.如果我通过以下方法在RuntimeException中包装CardException:
throw new RuntimeException(e)
Run Code Online (Sandbox Code Playgroud)
和/或从catch中删除签名只是捕获(e)而不键入它,它可以工作,但是我从异常中丢失了一些信息,比如消息.
作为注释,CardException是一个Exception,而不是RuntimeException.我不确定这是否重要.
Dón*_*nal 15
与Java不同,您不必声明Groovy方法抛出的(已检查的)异常,因为任何未声明的已检查异常都包含在UndeclaredThrowableException.所以这:
def createCharge(chargeParams) {
try {
def charge = Charge.create(chargeParams)
} catch (CardException e) {
throw e
}
}
Run Code Online (Sandbox Code Playgroud)
实际上与以下内容相同:
def createCharge(chargeParams) throws UndeclaredThrowableException {
try {
def charge = Charge.create(chargeParams)
} catch (CardException e) {
throw new UndeclaredThrowableException(e)
}
}
Run Code Online (Sandbox Code Playgroud)
上面抛出的异常显然不会被以下情况所捕获:
try {
service.createCharge(chargeParams)
} catch(CardException e) {
}
Run Code Online (Sandbox Code Playgroud)
但它将被捕获:
try {
service.createCharge(chargeParams)
} catch(e) {
}
Run Code Online (Sandbox Code Playgroud)
因为这只是一个简写:
try {
service.createCharge(chargeParams)
} catch(Exception e) {
}
Run Code Online (Sandbox Code Playgroud)
与Java不同,您不必声明Groovy方法抛出的(已检查)异常,因为任何未声明的已检查异常都包含在UndeclaredThrowableException中.
您似乎暗示Groovy通过UndeclaredThrowableException包装已检查的Exceptions,但情况并非如此.如果Grails服务抛出未经检查的异常,则异常最终会被UndeclaredThrowableException包装,但这是一个java.lang.reflection机制,只有在涉及代理类时才会发生.
碰巧就是这种情况,因为涉及Grails服务.我不确定至少有一个代理类涉及多少代理类:一个执行事务处理的类(由Spring提供).
该类将使用事务包装Service中的任何方法,并在发生RuntimeException时回滚事务.默认情况下,Spring事务管理在检查Exception时不会回滚.
Java的
这在普通的旧java中是有意义的,因为开发人员将在应用程序代码中看到异常,并将被警告要对它做些什么.如果开发人员很聪明,他将在交易范围内处理任何例外情况.如果他不回滚交易,他基本上会说:"在这种情况下,交易提供的数据完整性对我来说并不重要.我会以其他方式从这个错误中恢复过来"
Groovy的
这在Groovy世界中没有意义,因为Groovy编译器不强制处理异常.它实际上以与RuntimeExceptions完全相同的方式处理异常.
但是有一个警告:反射机制看到代理抛出的异常不在原始服务的方法签名中.这是可能的,因为:
因为使用的反射机制来自Java,所以它必须符合Java规则.所以它必须在RuntimeException中包装Exception,在这种情况下是UndeclaredThrowableException.
Grails的
现在它变得非常棘手,因为如果从Controller调用Service方法并发生异常.您将看到RuntimeException冒泡(由于某些隐藏机制),但您的事务将不会回滚(因为某些隐藏机制).
这种行为非常危险,因为开发人员必须记住正确处理任何异常(编译器无法帮助)或开发人员必须确保使用@Transactional(rollbackFor = Throwable)正确指示任何服务.
这是一个设计问题,我认为Grails的开发人员在他们第一次设计时忽略了这一点.但我认为默认行为是如此错误而且非常危险,这应该真正改变.
| 归档时间: |
|
| 查看次数: |
4109 次 |
| 最近记录: |