按照Creating FacesMessage in action method outside JSF conversion/validation mechanism?中的上一个问题,我正在尝试处理托管bean之外的业务层抛出的异常。
策略是在PhaseListener中搜索和转换业务异常以面对消息。
它按照我的预期工作,但我只是想知道我是刚刚重新发明轮子,还是以错误的方式做到了?
这是我的代码示例代码段:
public class BusinessExceptionHandler implements PhaseListener {
@Override
public void afterPhase(PhaseEvent phaseEvent) {
ExceptionHandler exceptionHandler = phaseEvent.getFacesContext().getExceptionHandler();
// just debugging the handled exception, nothing here
/*
for (ExceptionQueuedEvent event : exceptionHandler.getHandledExceptionQueuedEvents()) {
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
System.out.println("handled exception : " + context.getException());
}*/
for (Iterator<ExceptionQueuedEvent> it = exceptionHandler.getUnhandledExceptionQueuedEvents().iterator();
it.hasNext();) {
ExceptionQueuedEvent event = it.next();
ExceptionQueuedEventContext eventContext = (ExceptionQueuedEventContext) event.getSource();
Throwable e = eventContext.getException();
System.out.println("unhandled exception : " + e);
// get the root cause exception
while (e.getCause() != null) {
e = e.getCause();
}
System.out.println("cause exception : " + e +
", cause exception is BE : " + (e instanceof BusinessException));
// handle BE
if (e instanceof BusinessException) {
BusinessException be = (BusinessException) e;
System.out.println("processing BE " + be);
FacesMessage message = Messages.getMessage(
"com.corejsf.errors",
be.getMessage(),
be.getParamValues()
);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
it.remove(); // remove the exception
// works fine without this block, if BE is thrown, always return to the original page
/*
NavigationHandler navigationHandler = context.getApplication().getNavigationHandler();
System.out.println("navigating to " + context.getViewRoot().getViewId());
navigationHandler.handleNavigation(context, context.getViewRoot().getViewId(), null);
*/
}
}
}
@Override
public void beforePhase(PhaseEvent phaseEvent) {
}
@Override
public PhaseId getPhaseId() {
return PhaseId.INVOKE_APPLICATION;
}
}
谢谢!
此致 Albert Kam
答案 0 :(得分:3)
不确定为什么要走这条路,创建和注册自己的异常处理程序非常简单。虽然Seam Catch(http://seamframework.org/Seam3/CatchModule和http://docs.jboss.org/seam/3/catch/3.0.0.Alpha1/reference/en-US/html_single/)更容易。我还没有JSF桥,但它很容易做到。然后你所要做的就是写一个处理特定异常的方法,你就完成了!
答案 1 :(得分:2)
您的方法是JSF 1.x和JSF 2.x异常处理方法的混合。由于你使用的是JSF 2.x,我建议使用一个纯粹的JSF 2.x方法而没有PhaseListener
并且在新ExceptionHandler
API的帮助下。
您可以在“JSF 2.0:完整参考”一书的第282页找到一个处理ViewExpiredException
的示例,该书可在线获取here(点击第1页)结果链接)。