在 Java EE 前端方法中处理服务层异常 [英] Handling service layer exception in Java EE frontend method
问题描述
我维护一个 Web 应用程序,该应用程序有一个带有 JSF 标记 <f:event
的页面.我在服务类中重写了一个方法,以便它抛出业务异常.但是,当业务异常被抛出时,它不会被托管 bean 捕获,并且异常会显示在页面上.似乎我的代码 try/catch
不起作用.
I maintain a web application that have a page with the JSF tag <f:event
. I have rewrote a method in a service class for it to throw a business exception. However, when the business exception is thrown, it isn't caught in managed bean and the exception is showed on the page. Seems that my code try/catch
doesn't work.
在 XHTML 中:
<f:event listener="#{resourceBean.init(enrollment)}" type="preRenderView" />
Managed Bean 中的监听器方法:
Listener method in Managed Bean:
private boolean canCreateResource;
public void init(Enrollment enrollment) {
(...)
try {
canCreateResource = resourceService.canCreateResource(enrollment);
} catch (BusinessException e) {
canCreateResource = false;
}
}
服务类中的方法:
public boolean canCreateResource(Enrollment enrollment) {
if (...) {
if (mandateService.isCoordinator(user, course)) {
return true;
} else {
throw new BusinessException("Undefined business rule.");
}
}
return false;
}
根据我在其他网站上阅读的内容,我想我必须实现一些 JSF 的处理程序类.但是哪个以及如何?
From what I read on other sites, I suppose I have to implement some JSF's handler class. But which and how?
已编辑
OBS 1:BusinessException
类扩展了 RuntimeException
类.
OBS 1: The BusinessException
class extends RuntimeException
class.
OBS 2:创建属性 canCreateResource
来控制按钮的呈现.
OBS 2: The attribute canCreateResource
was created to control the render of a button.
推荐答案
因为你抛出了 RuntimeException
来自 EJB.
It's because you threw a RuntimeException
from an EJB.
当此类 RuntimeException
未使用 @ApplicationException
,然后 EJB 容器会将其包装在 javax.ejb.EJBException
中并重新抛出它.这样做是因为运行时异常通常仅用于指示代码逻辑中的错误,即程序员的错误而不是最终用户的错误.你知道,NullPointerException
、IllegalArgumentException
、IndexOutOfBoundsException
、NumberFormatException
和朋友们.这允许 EJB 客户端对此类运行时异常有一个包罗万象的点,例如 catch (EJBException e) { 服务层或我们使用它的方式存在错误!}
When such RuntimeException
is not annotated with @ApplicationException
, then the EJB container will wrap it in an javax.ejb.EJBException
and rethrow it. This is done so because runtime exceptions are usually only used to indicate bugs in code logic, i.e. programmer's mistakes and not enduser's mistakes. You know, NullPointerException
, IllegalArgumentException
, IndexOutOfBoundsException
, NumberFormatException
and friends. This allows the EJB client to have one catch-all point for such runtime exceptions, like catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }
如果您尝试过 catch (Exception e)
并检查了实际的异常,那么您就会注意到这一点.
If you had tried catch (Exception e)
and inspected the actual exception, then you'd have noticed that.
相应地修复您的 BusinessException
类以添加该注释,然后它将被识别为真正的应用程序异常,而不是包装在 EJBException
中:
Fix your BusinessException
class accordingly to add that annotation, it will then be recognized as a real application exception and not be wrapped in an EJBException
:
@ApplicationException(rollback=true)
public class BusinessException extends RuntimeException {
// ...
}
请注意,如果您抛出非RuntimeException
,那么您仍然需要使用rollback=true
显式地保留注释,因为默认情况下它不会执行回滚,与没有注释的 RuntimeException
相反.
Do note that in case you throw an non-RuntimeException
, then you still need to keep the annotation on that, explicitly with rollback=true
, because by default it wouldn't perform a rollback, on the contrary to a RuntimeException
without the annotation.
@ApplicationException(rollback=true)
public class BusinessException extends Exception {
// ...
}
总结:
RuntimeException
从事务性 EJB 方法抛出将执行完全回滚,但异常将被包装在EJBException
中.RuntimeException
和@ApplicationException
来自事务性 EJB 方法,只有在显式设置rollback=true
时才会执行完全回滚.Exception
来自事务性 EJB 方法将不会执行完全回滚.Exception
with@ApplicationException
来自事务性 EJB 方法仅在显式设置rollback=true
时执行完全回滚.
RuntimeException
thrown from transactional EJB method will perform full rollback, but exception will be wrapped inEJBException
.RuntimeException
with@ApplicationException
from transactional EJB method will only perform full rollback whenrollback=true
is explicitly set.Exception
from transactional EJB method will not perform full rollback.Exception
with@ApplicationException
from transactional EJB method will only perform full rollback whenrollback=true
is explicitly set.
请注意,@ApplicationException
继承自自定义异常的所有子类,因此您无需对所有子类重复.最好将它作为一个抽象类.另请参阅下面链接的相关问题中的示例.
Note that @ApplicationException
is inherited over all subclasses of the custom exception, so you don't need to repeat it over all of them. Best would be to have it as an abstract class. See also the examples in the related question linked below.
这篇关于在 Java EE 前端方法中处理服务层异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!