EJB3.1系统异常与javax.ejb.EJBException

时间:2014-02-13 22:17:02

标签: java java-ee exception java-ee-6 ejb-3.1

在提出我的问题之前,只有一些关于EJB3.1异常的背景知识 -

应用程序异常包含

  • 用户定义的已检查或未检查的异常 @ApplicationException注释

  • 所有已检查的例外情况

    java.lang.Exception&它是子类例外 除了java.rmi.RemoteException&它是子类例外

系统例外由

组成
  • java.rmi.RemoteException及其子类异常

  • 所有未经检查的例外

    java.lang.RuntimeException及其子类异常
    java.lang.Error及其子类异常

以下是我在此book

中读到的声明
  

在EJB系统中,客户端不会例外,遇到此类异常时,不会将这些异常传递给客户端,而是在javax.ejb.EJBException中包含。

我的问题 -

  1. 上面描述的所有应用程序异常是否应该由EJB直接抛给客户端?
  2. 如果在抛出到客户端之前将系统异常包装在javax.ejb.EJBException中,那么javax.ejb.EJBException是否被视为系统异常?

2 个答案:

答案 0 :(得分:7)

IndoKnight,您对Java EE框架中的Exception语义如何完美总结..工作。

这是两个唯一的行“bean提供者”,也就是你和我,需要了解Java EE中的异常:

对于bean可能存在的其他约束,您可以完全自由地从任何类型的异常或错误中恢复。如果你从异常中恢复过来,那么恭喜 - 再也没有问题了=)

相关约束可以是例如“使用容器管理的事务划分的企业bean不得使用任何干扰容器的事务划分边界的事务管理方法”来引用Java EE 7 tutorial页面48-2 (您希望以编程方式设置容器管理事务的回滚,使用EJBContext.setRollbackOnly() )。

与任何类型的Java应用程序一样,您也不鼓励处理从非常低级别抛出的ThrowableError。从理论上讲,RuntimeException属于这一类,因为它如此着名地表示“开发者错误”,就像“完全出乎意料” - 但我们都知道它不是。

基本上,一个意外的异常(运行时异常+我们假设来自其他人的其他shit)被认为是代码无法处理的,应该由服务器处理。服务器需要通过在日志中打印有关它的内容来处理“不可处理的”异常(参见EJB 3.2 specification,页面204 )(我将进入详细信息a稍后!)。

更具体地......

你问(这是我相信或坚持的):

  

是否应抛出上述所有应用程序异常   直接由EJB到客户端?

是。除非您明确声明应该使用ApplicationException的rollback属性,否则不会回滚事务(如果一个处于活动状态)。抛出异常的Java代码是很自然的事情。 Java EE无意拆除此编程模型。所以继续,抛出你喜欢的已检查异常,强制客户端尝试捕获它们或将运行时异常标记为应用程序异常并抛出这些异常。快乐的投掷!

  

如果之前将系统异常包装在javax.ejb.EJBException中   扔给客户端,然后将javax.ejb.EJBException视为   系统异常?

,但不是因为您提供的原因。要清楚,没有名为SystemException的类型。只是花哨的措辞来描述那些大多数那些没有想到的bean可能发生的异常,并且很可能,它们来自EJB容器。您的代码绝对不应该抛出EJBException。这样做可能只会阻碍服务器的思维。由于您不拥有代码,因此也不能将异常注释为@ApplicationException,它由Java EE API提供。您可以扩展EJBException,但将代码伪装成服务器代码库的一部分是没有任何意义的。最重要的是,由于 EJBException扩展了RuntimeException ,我认为将EJBException归类为“系统级异常”是安全的。

留意魔鬼

某些远程客户端将收到RemoteException而不是EJBException。

在一个巨大的企业项目中你甚至可能都没有意识到的

拦截器,即使你从来没有计划,也可以吞下你的方法抛出的异常进行活动事务 commit 让他这样做。

我敢打赌,您认为使用Throwable.getCause()始终可以检索已撤消的异常。请注意EJB 3.2 specification并未说明容器必须或应该提供对被抑制原因的引用。实际上,容器唯一要做的就是记录异常。然后,如果bean不是单例,则必须丢弃bean实例并且不再使用它。此外,如果bean是一个消息驱动的bean,那么只有那时才需要“包装”。未指定如何“包装”异常。超级便携式酷代码也应该看看Throwable.getCause()方法和Throwable.getSuppressed()。不要盲目期望在处理代码中始终找到原始异常。

返回void的

异步方法(公共会话bean方法注释@Asynchronous )无法将异常传播到其客户端。因此,他们不得声明或抛出应用程序异常(请参阅EJB 3.2 specification第82页)。请注意,当您调用异步方法时,可能是服务器无法提供线程资源来为您的请求提供服务,如果是这样,他需要抛出一个.. EJBException(第48页) !

答案 1 :(得分:6)

  1. 是的,或多或少是他们的工作方式。有关EJB行为的更多详细信息,请查看以下博客文章:Link
  2. 同样来自question

      

    存在应用程序异常时应抛出异常   业务逻辑错误,而不是系统错误。

         

    有一个重要的区别:应用程序异常没有   自动导致事务回滚。客户有一个   抛出应用程序异常后恢复的机会。

         

    应用程序异常将被发送到客户端而不会被重新打包   作为EJBException。因此,您可以使用它们来报告验证   错误或业务逻辑问题,他们将到达客户端。

    1. javax.ejb.EJBException扩展RuntimeException所以是的,这是系统异常。
    2. 与此相关的常见场景:如果您的应用程序代码中有未被捕获的RuntimeException,它将回滚。这是非常有用的默认行为。