我有一个关于如何在某些特殊情况下处理EJBExceptions的问题。
在我们的应用程序中,EJB(3.0)DataAccessObjects(DAO)负责所有数据库访问,这些访问在应用程序的其他部分中使用。
预计数据库层中存在异常,例如由于乐观锁定或数据库约束违规。通常抛出DOA类之外的异常,因为它们是在提交自动JTA事务时发生的。然后调用类接收包含在EJBException
。
在大多数情况下,忽略或记录并重新抛出EJBException
是最好的,因为我们的JMS将触发MessageDrivenBeans的自动重试。在两种情况下,我们不希望异常被提及,因为它们具有不想要的副作用。
在我们的JSF网站中,我们使用以下模式显示用户友好的消息:
@ManagedBean
@ViewScoped
public class MyDataController {
@EJB
private MyDataDao myDataDao ;
public void addData(){
FacesMessage msg;
try {
Data data = new Data();
// Data gets filled
myDataDao.addData(data);
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Succes",
data.getName());
}
catch (EJBException e) {
LOGGER.warn("Failed to add data"newCompanyName, e);
if (ExceptionUtils.getRootCause(e) instanceof SQLIntegrityConstraintViolationException) {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL, "Failed",
data.getName());
}
else {
msg = new FacesMessage(FacesMessage.SEVERITY_FATAL,
"Failed to add data for unknown reason", data.getName());
}
}
}
}
在相关案例中,我们从定时任务(使用@Schedule
创建)调用数据库。但是,当运行它时(至少在Weblogic中)发生(连续两次?)异常时,此任务将被销毁。对我们来说,即使处理过程中出现异常,此任务仍然保持运行非常重要。
我们通过捕获并记录所有EJBExceptions
来实现这一目标,如in this answer和in this answer所述。 (实际上,在我们的例子中,我们决定捕获所有例外情况。)
上述解决方案大多按预期工作。但是,我们最近发现错误也包含在EJBException
中。例如OutOfMemoryError
。在这种情况下,它导致吞下错误,禁用Weblogic中的正常机制,如果OutOfMemoryError
,将重启应用程序。
实际上,这已将Errors
降级为Exceptions
。
我唯一的解决方案是检查递归检查类型Error
实例的异常及其原因,如果是这种情况,请重新抛出EJBException
。
在这些情况下处理EJB异常的正确方法是什么?