处理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通常只用于指示代码逻辑中的错误,即程序员的错误而不是最终用户的错误。 你知道, NullPointerExceptionIllegalArgumentExceptionIndexOutOfBoundsExceptionNumberFormatException和朋友。 这允许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 { // ... } 

总结如下:

  1. 从事务性EJB方法抛出的RuntimeException将执行完全回滚,但exception将被包装在EJBException
  2. 事务性EJB方法中带有@ApplicationException RuntimeException只会在显式设置rollback=true时执行完全回滚。
  3. 事务性EJB方法的Exception不会执行完全回滚。
  4. 事务性EJB方法中的@ApplicationException Exception只有在明确设置了rollback=true时才会执行完全回滚。

请注意,@ @ApplicationExceptioninheritance自定义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>标签。