JSF ajax请求中的异常处理

10

当处理JSF ajax请求时抛出异常,我应该如何处理异常并访问堆栈跟踪信息?目前,仅在JSF项目阶段设置为开发时,在JavaScript警报中获取异常类名和消息。更糟糕的是,当JSF项目阶段设置为生产时,没有任何可视反馈,并且服务器日志不显示有关异常的任何信息。

如果相关的话,我正在使用Netbeans中的GlassFish。


您是否想在异步请求期间在网页上显示完整的异常堆栈跟踪? - Tiny
不是。我在页面上有一个<h: commandButton>,当按下时(使用ajax处理),会导致异常。(http://i.imgur.com/PdgQvP9.png),但Netbeans中的Glassfish输出不显示堆栈跟踪。(http://i.imgur.com/a7jqUVz.png)。另一方面,如果是普通的http请求,则堆栈跟踪将显示在HTML输出中(http://i.imgur.com/EgxHSP4.png),并且Netbeans中的Glassfish服务器输出将显示堆栈跟踪(http://i.imgur.com/6izzfPs.png)。 - Ranjith
我想在 Netbeans 的 Glassfish 输出中显示堆栈跟踪(如此处所示:http://i.imgur.com/6izzfPs.png),当 Ajax 请求时发生错误。 @Tiny - Ranjith
1个回答

23

这个问题已知,并在其他地方,包括OmniFaces FullAjaxExceptionHandler示例中得到了充分的阐述。

默认情况下,在 JSF 异步请求期间发生异常时,如果操作成功执行或未执行,最终用户将不会得到任何形式的反馈。在 Mojarra 中,只有在项目阶段设置为开发阶段时,最终用户才会看到一个仅包含异常类型和消息的简单 JavaScript 警报。

技术原因是异步请求(即 Ajax 请求)默认不返回同步响应(即完整页面)。相反,它们返回小型指令和部分内容以更新已打开页面的 HTML DOM 树。当出现异常时,这些指令基本上完全不存在。相反,一些错误信息被发送回来。通常可以在 Ajax 组件的 onerror 属性中处理它们,并显示一个警报或进行 window.location 更改。至少,这是 JSF 从您期望的方式。

为了捕获和记录异常并可选地更改整个响应,您基本上需要创建自定义ExceptionHandler。标准 JSF 不幸的是没有提供默认的异常处理程序(至少没有一个明智的实现)。在您的自定义异常处理程序中,您将能够获得引起所有麻烦的 Exception 实例。

这是一个启动示例:

public class YourExceptionHandler extends ExceptionHandlerWrapper {

    private ExceptionHandler wrapped;

    public YourExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public void handle() throws FacesException {
        FacesContext facesContext = FacesContext.getCurrentInstance();

        for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents().iterator(); iter.hasNext();) {
            Throwable exception = iter.next().getContext().getException(); // There it is!

            // Now do your thing with it. This example implementation merely prints the stack trace.
            exception.printStackTrace();

            // You could redirect to an error page (bad practice).
            // Or you could render a full error page (as OmniFaces does).
            // Or you could show a FATAL faces message.
            // Or you could trigger an oncomplete script.
            // etc..
        }

        getWrapped().handle();
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

}
为了使其运行,请按照以下步骤创建自定义的ExceptionHandlerFactory:ExceptionHandlerFactory
public class YourExceptionHandlerFactory extends ExceptionHandlerFactory {

    private ExceptionHandlerFactory parent;

    public YourExceptionHandlerFactory(ExceptionHandlerFactory parent) {
        this.parent = parent;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        return new YourExceptionHandler(parent.getExceptionHandler());
    }

}

需要在faces-config.xml中进行注册,如下所示:

<factory>
    <exception-handler-factory>com.example.YourExceptionHandlerFactory</exception-handler-factory>
</factory>

或者,您可以尝试使用 OmniFaces。它将通过在 web.xml 中配置 <error-page> 来完全透明地确保异步请求期间的异常表现与同步请求期间的异常相同。

另请参阅:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接