3

我在 JBoss 7.1 和 Richfaces 4.1 中有一个 JSF Web 应用程序。我尝试在 web.xml 中配置自定义错误页面,但遇到了问题,这不适用于 AJAX 请求。作为一种解决方案,我尝试使用Omnifaces FullAjaxExceptionHandler来很好地显示错误页面。

但是,我想添加一个表单,允许用户输入其他信息并将其与例外一起作为电子邮件发送给我。问题是在错误页面上,提交按钮不起作用。当我单击它时,错误页面刚刚重新加载。在下一次单击时,一切都按预期工作。

错误页面模板中的小菜单中的 h:commandlinks 也会出现同样的问题。

我对 JSF 很陌生,所以我真的不知道为什么会发生这种情况以及如何解决它。还是有更好的方法来实现这一点?

4

1 回答 1

1

这与JSF 规范问题 790相关,归结为 ajax 更新某些组件,而该组件又包含一个或多个<h:form>组件,不能正确更新这些表单的新视图状态标识符。

此问题已在即将发布的 JSF 2.2 中修复,但在此之前,您必须使用以下基于 JavaScript 的解决方法。

jsf.ajax.addOnEvent(function(data) {
    if (data.status == "success") {
        var viewState = getViewState(data.responseXML);

        if (viewState) {
            for (var i = 0; i < document.forms.length; i++) {
                var form = document.forms[i];

                if (!hasViewState(form)) {
                    createViewState(form, viewState);
                }
            }
        }
    }
});

function getViewState(responseXML) {
    var updates = responseXML.getElementsByTagName("update");

    for (var i = 0; i < updates.length; i++) {
        var update = updates[i];

        if (update.getAttribute("id") == "javax.faces.ViewState") {
            return update.firstChild.nodeValue;
        }
    }

    return null;
}

function hasViewState(form) {
    for (var i = 0; i < form.elements.length; i++) {
        if (form.elements[i].name == "javax.faces.ViewState") {
            return true;
        }
    }

    return false;
}

function createViewState(form, viewState) {
    var hidden;

    try {
        hidden = document.createElement("<input name='javax.faces.ViewState'>"); // IE6-8.
    } catch(e) {
        hidden = document.createElement("input");
        hidden.setAttribute("name", "javax.faces.ViewState");
    }

    hidden.setAttribute("type", "hidden");
    hidden.setAttribute("value", viewState);
    hidden.setAttribute("autocomplete", "off");
    form.appendChild(hidden);
}

只需将其包含在错误页面的<h:outputScript name="some.js" target="head">内部即可。<h:body>如果您不能保证页面使用 JSF ,那么您可能需要在调用之前<f:ajax>添加额外的if (typeof jsf !== 'undefined')检查。jsf.ajax.addOnEvent()

JSF 组件库 PrimeFaces 已经在其核心 ajax 引擎中解决了这个问题,所以如果您碰巧已经使用它,您可能希望用<f:ajax>PrimeFaces 替换所有链接/按钮。

也可以看看:

于 2012-11-12T14:53:42.387 回答