Объект не поддерживает это свойство или метод с комбинацией тайм-аута первичных лиц и омнифейсов.

Установка: JSF, PrimeFaces 3.2, Omnifaces 1.1, JBoss AS 7.1.1, Final, Mojarra 2.1.7

У меня есть простая страница (указана ниже), и я настроил омнифейсы для работы с ViewExpiredExceptions для вызовов ajax. Когда срок действия указанной ниже страницы истекает, и я нажимаю кнопку с простыми лицами (ajax) в IE8, появляется страница ошибки с истекшим сроком действия, но со следующей ошибкой javascript:

Сообщение: Объект не поддерживает это свойство или метод, Строка: 1 Символ: 5500 Код: 0 URI: blah blah/mywebapp/javax.faces.resource/primefaces.js.xhtml?ln=primefaces&v=3.2

В других браузерах ошибки не возникает.

Моя страница (home.xhtml):

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    template="/WEB-INF/templates/layout.xhtml"> 
    <ui:define name="body">
        <h:form id="form_search">
            <p:commandButton id="idbtn1"
                actionListener="#{bean.doSomething}"
                value="Do something (ajax)!">
            </p:commandButton>
            <p:commandButton id="idbtn2" ajax="false"
                actionListener="#{bean.doSomething}"
                value="Do something!">
            </p:commandButton>

        </h:form>
    </ui:define>
</ui:composition>

Страница ошибки тайм-аута: expired.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    template="/WEB-INF/templates/layout.xhtml">
    <ui:define name="body">
    Your session has timed out.
    </ui:define>
</ui:composition>

Шаблон layout.xhtml

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets">

<f:view contentType="text/html">
    <h:head>
        <f:facet name="first">
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
            <meta http-equiv="Cache-Control" content="no-cache, no-store, must-    revalidate" />
            <meta http-equiv="Pragma" content="no-cache" />
            <meta http-equiv="Expires" content="0" />
        </f:facet>
        <base href="${facesContext.externalContext.requestContextPath}" />
    </h:head>
    <h:body>
        <ui:insert name="body"></ui:insert>
    </h:body>
</f:view>
</html>

Web.xml имеет среди прочего:

    <error-page>
        <exception-type>javax.faces.application.ViewExpiredException</exception-type>
        <location>/WEB-INF/errorpages/expired.xhtml</location>
    </error-page>

    <filter>
        <filter-name>facesExceptionFilter</filter-name>
        <filter-class>org.omnifaces.filter.FacesExceptionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>facesExceptionFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

Когда я нажимаю вторую кнопку после истечения срока действия, страница с истекшим сроком действия отображается без ошибок javascript.

Любые идеи?


person bac    schedule 10.10.2012    source источник


Ответы (1)


Это известная проблема PrimeFaces update="@all" в браузерах на базе IE. Все представление заменено на document.write(), однако браузеры на основе IE не загружают/инициализируют должным образом какие-либо ресурсы <script>. См. также эту тему форума PrimeFaces. Это будет исправлено для PrimeFaces версии 3.4.2.

До тех пор вы можете обойти это, используя следующий JavaScript

var originalPrimeFacesAjaxResponseFunction = PrimeFaces.ajax.AjaxResponse;
PrimeFaces.ajax.AjaxResponse = function(responseXML) {
   var newViewRoot = $(responseXML.documentElement).find("update[id='javax.faces.ViewRoot']").text();

    if (newViewRoot) {
       $('head').html(newViewRoot.substring(newViewRoot.indexOf("<head>") + 6, newViewRoot.indexOf("</head>")));
       $('body').html(newViewRoot.substring(newViewRoot.indexOf("<body>") + 6, newViewRoot.indexOf("</body>")));
    }
    else {
        originalPrimeFacesAjaxResponseFunction.apply(this, arguments);
    }
};

который необходимо загрузить после собственных ресурсов JS PrimeFaces; это можно сделать, сославшись на него в <h:body> с помощью target="head".

<h:body>
    <h:outputScript name="script.js" target="head">
    ...
</h:body>

Обратите внимание, что это предполагает, что текущее представление использует компоненты PrimeFaces, которые, в свою очередь, должны автоматически включать сценарии primefaces.js и jquery.js. В противном случае вы должны объявить их вручную.

person BalusC    schedule 10.10.2012
comment
Кстати, чтобы сломать его, добавьте oncomplete=showConfirmDlg(); до первой кнопки. Тогда на этот раз он все равно будет показывать ошибку, жалуясь на script.js. showConfirmDlg выше — это команда p:remote. Добавьте ‹p:remoteCommand name=showConfirmDlg › ‹f:setPropertyActionListener value=#{sessionScope.render} target=#{requestScope.render} /› ‹/p:remoteCommand›, чтобы увидеть, что это прерывается сообщением: Объект не поддерживает это свойство или метод Строка: 3, Char: 4, Код: 0 URI: blah/javax.faces.resource/js/script.js.xhtml - person bac; 11.10.2012
comment
Вам нужно будет добавить дополнительную проверку, если responseXML или responseXML.documentElement не являются неопределенными. - person BalusC; 11.10.2012
comment
разницы не вижу, буду пробовать дальше - person bac; 11.10.2012
comment
и responseXML, и responseXML.documentElement хороши. На самом деле он идет по адресу: originalPrimeFacesAjaxResponseFunction.apply(this, arguments); так что не знаю что делать в таком случае - person bac; 15.10.2012