为什么抛出EJBException是一个“推荐”实践? [英] Why throwing an EJBException is a "recommended" practice?

查看:139
本文介绍了为什么抛出EJBException是一个“推荐”实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不断地从许多同行的开发者那里得到这个建议。根据我的经验,我发现EJBExceptions非常适合从bean实例的角度来看世界末日(比如当一些东西如此错误,bean实例本身无法恢复时)。如果一个实例可以恢复,我认为最好是抛出一个应用程序异常。



这是一次又一次遇到的模式:

 
private SomeResource资源;
ejbCreate:
resource = allocateResource(...);

omMessage:
try {
...
} catch(JMSException e){
throw new EJBException(e);
}

ejbRemove:
freeResource(resource);

IMHO这是一个反模式,导致资源泄露。



编辑:具体来说,EJB规范说如果一个bean从业务方法中抛出一个运行时异常(而EJBException是一个运行时异常),那么在不调用ejbRemove的情况下,bean被丢弃。



这是一个反对抛出EJBException的相关示例吗?
当EJBException被抛出时,相关的情况是什么?

解决方案

抛出 EJBException如果EJB 无法从遇到的异常恢复,则EJB规范(EJB 3中为14.2.2)推荐使用。该规范还表示,EJB可以合理地允许(未选中)系统异常传播到容器。



我同意您的阅读规范,在这种情况下,循环回调方法不会被容器调用,因此您担心在 ejbRemove()回调中通常会发生的任何资源整理将不会发生,因此有资源泄露的危险。



我的经验是因为缺乏防御性编码而出现了许多棘手的问题。 情况X不能发生在行为良好的系统中,如果这样,整个系统就会损坏,所以我不会为这种可能性编写代码。然后,我们得到一些有趣的星星和操作员错误的对齐,不能发生几次快速连续发生,意外的副作用踢,导致确实难以诊断问题。



所以我会说:


  1. 做一切你可以离开Bean实例处于下一个状态调用业务方法可能能够工作。这可能意味着捕获异常并关闭错误的资源。在这种情况下,您可以选择告诉呼叫者sorry guv,该请求无效,但也许如果稍后重试...我通过抛出一个 TransientException 检查异常。

  2. 如果您在 ejbRemove 中没有重要的内务管理,那么您可以允许SystemExceptions进行传播 - 但是我不确定这是友好的。你依赖一个库,它会抛出一个 NullPointerException 。实际上,如果你有重要的内务管理,那么实际上是更强大的抓住并重新抛出 TransientException

  3. 所有异常并至少尝试清理。然后,您可以选择重新推荐 EJBException 或系统异常,以便实例被销毁,但至少您尝试进行内务管理。


I keep getting this "suggestion" from many fellow developers over and over again. In my experience I've found that EJBExceptions are well-suited for "end of the world" from the bean instance perspective (like when something is so wrong that the bean instance cannot recover by itself). If an instance can recover, I think it's better to throw an application exception.

Here is the pattern that I meet over and over again:

private SomeResource resource;
ejbCreate:
    resource = allocateResource(...);

omMessage:
    try {
    ...
    } catch (JMSException e) {
        throw new EJBException(e);
    }

ejbRemove:
    freeResource(resource);

IMHO this is a antipattern that causes resource leaks.

EDIT: Specifically, the EJB specification says that if a bean throws a runtime exception (and EJBException is a runtime exception) from the business method, then the bean is discarded without calling ejbRemove on it.

Is this a relevant example against throwing an EJBException? What are the relevant cases when EJBException should be thrown?

解决方案

The throwing of EJBException is recommended by the EJB spec (14.2.2 in the EJB 3) in the cases where the EJB cannot recover from an exception it encounters. The spec also says that the EJB can reasonably allow (unchecked) System Exceptions to propagate to the container.

I agree with your reading of the spec that in such cases life-cycle callback methods will not be invoked by the container, and hence your concern that any resource-tidy up that would normally happen in the ejbRemove() callback will not happen and so there's a danger of resource leakage.

My experience is that very many tricky problems arise because of a lack of defensive coding. "Situation X cannot occur in a well behaved system, and if it does then the whole system is broken, so I'll not code for that eventuality." Then we get some "interesting" alignment of the stars and operator errors and the "can't happen" happens several times in quick succession and unanticipated side-effects kick in leading to really difficult to diagnose problems.

Hence I would say:

  1. Do everything you can to leave the Bean instance in a state where the next invocation of a business method might be able to work. This might mean catching exceptions and closing resources that are in error. In this case you may then chose to tell the callers, "sorry guv, that request didn't work, but maybe if you retry later ..." I do that by throwing a TransientException checked exception.
  2. If you have no important housekeeping in ejbRemove then you can allow SystemExceptions to propogate - but I'm not sure that this is friendly. You depend upon a library and it throws a NullPointerException. Is is actually more robust to catch and rethrow TransientException?
  3. If you do have important housekeeping, then I think you do need to catch all exceptions and at least attempt the cleanup. You may then choose to rethrow EJBException or a system exception so that the instance is destroyed, but at least you've tried to do the housekeeping.

这篇关于为什么抛出EJBException是一个“推荐”实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆