处理Java EE前端方法中的服务层exception
我使用JSF标记<f:event
维护了一个包含页面的Web应用程序。 我已经重写了一个服务类中的方法,以引发业务exception。 但是,在引发业务exception时,不会在托pipebean中捕获,并在页面上显示exception。 似乎我的代码try/catch
不起作用。
在XHTML中:
<f:event listener="#{resourceBean.init(enrollment)}" type="preRenderView" />
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的处理程序类。 但是,如何?
EDITED
OBS 1: BusinessException
类扩展了RuntimeException
类。
OBS 2:创build属性canCreateResource
来控制button的呈现。
这是因为你从EJB抛出了一个RuntimeException
。
当这样的RuntimeException
没有用@ApplicationException
注释时,那么EJB容器将把它包装在一个javax.ejb.EJBException
并重新抛出它。 这样做是因为运行时exception通常只用于指示代码逻辑中的错误,即程序员的错误而不是最终用户的错误。 你知道, NullPointerException
, IllegalArgumentException
, IndexOutOfBoundsException
, NumberFormatException
和朋友。 这允许EJB客户端对这样的运行时exception拥有一个捕获所有的点,比如catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }
catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }
如果你尝试catch (Exception e)
并检查了实际的exception,那么你会注意到这一点。
相应地修复您的BusinessException
类以添加该注释,然后将其识别为真正的应用程序exception,而不是包装在EJBException
:
@ApplicationException(rollback=true) public class BusinessException extends RuntimeException { // ... }
请注意,如果你抛出一个非RuntimeException
,那么你仍然需要保留注释,显式地使用rollback=true
,因为默认情况下,它不会执行回滚,相反,不带注释的RuntimeException
。
@ApplicationException(rollback=true) public class BusinessException extends Exception { // ... }
总结如下:
- 从事务性EJB方法抛出的
RuntimeException
将执行完全回滚,但exception将被包装在EJBException
。 - 事务性EJB方法中带有
@ApplicationException
RuntimeException
只会在显式设置rollback=true
时执行完全回滚。 - 事务性EJB方法的
Exception
不会执行完全回滚。 - 事务性EJB方法中的
@ApplicationException
Exception
只有在明确设置了rollback=true
时才会执行完全回滚。
请注意,@ @ApplicationException
inheritance自定义exception的所有子类,所以您不需要重复所有的子类。 最好将它作为一个抽象类。 请参阅下面链接的相关问题中的示例。
也可以看看:
- 让表示层(JSF)处理来自服务层(EJB)的业务exception
如果isCoordinator
方法最终可以抛出exception,则应该在canCreateResource
方法内添加一个try catch块。 你可以抛出你自己的exception或传播原来的exception。 在这两种情况下,您都必须在方法签名中声明它。 如果抛出BusinessException
:
public void canCreateResource(Enrollment enrollment) throws BusinessException
不要回报任何价值。 或者返回一个布尔值,但不要抛出任何exception。
在init
方法中的catch块中添加Facelet消息exception:
... } catch (BusinessException e) { this.canCreateResource = false; FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), "")); } }
同样在你的页面中,你必须添加<h:messages>
标签。