使用 Omnifaces 在 JSF 中对 Ajax 请求的异常处理:始终显示状态代码 200 而不是 500

Exception handling for Ajax requests in JSF using Omnifaces : always showing Status Code 200 instead of 500

我们目前正在为我们的 JSF Web 应用程序添加一个监控解决方案 (Dynatrace)。监视解决方案检查指示错误的状态代码,以标记用户会话中的问题。我们正在尝试使用 Omnifaces FullAjaxExceptionHander(参见 http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler)来处理 Ajax 异常并呈现错误页面。从屏幕截图中可以看出,Omnifaces 将错误代码设置为 500,但 POST 上的状态代码在 Chrome 中显示为 200。由于 Dynatrace 没有看到错误状态代码,因此它不会在用户会话中对此进行标记。

知道为什么没有在响应中设置状态代码吗?我以为我看到它在我们系统的 POST 上短暂地显示了 500 的状态代码,但现在它只再次显示 200。就在那时,我尝试了 Omnifaces 展示中的示例,但我只得到了 200 has well。

这是因为它在技术上是成功的 Ajax 响应。 IE。它已成功将错误页面内容作为 Ajax 响应 XML 正文中 <partial-response> 的一部分传送。

如果 Ajax 响应的状态为 500,则 JSF 根本不会解析 Ajax 响应 XML,而是调用 onerror 处理程序这反过来会触发任何已注册的自定义客户端代码。这是事情变得复杂的地方,因为它默认情况下不渲染任何东西,而 FullAjaxExceptionHandler 真的想利用现有的 JSF Ajax 渲染逻辑。

您最好的办法是检查您的监控服务是否提供基于 Java 的 API 来手动通知错误情况。如果是这样,则覆盖 FullAjaxExceptionHandler 方法之一来 ping 它。 shouldHandleExceptionRootCause() 是一个很好的候选者。如有必要,您还可以对异常执行 instanceof 检查以跳过某些异常。

我不熟悉 Dynatrace,但如果您使用 NewRelic,它会是这样的:

import com.newrelic.api.agent.NewRelic;

public class CustomExceptionHandler extends FullAjaxExceptionHandler {

    @Override
    protected boolean shouldHandleExceptionRootCause(FacesContext context, Throwable exception) {
        try {
            NewRelic.noticeError(exception);
        }
        catch (Exception e) {
            // Log a WARN line
        }

        return true;
    }
}

最后为它创建一个自定义 ExceptionHandlerFactory 并用它替换 faces-config.xml 中的 FullAjaxExceptionHandlerFactory