httpError: Http Transport вернул 0 код состояния

У меня есть страница входа:

<h:form id="f_login" >
    <f:passThroughAttribute name="data-ajax" value="false" />

    <h:messages id="message" showDetail="false" errorClass="error_msg" fatalClass="success_msg" infoClass="info_msg" warnClass="warning_msg" />

    <h:inputText value="#{loginWEB.user.email}" >
        <f:passThroughAttribute name="placeholder" value="Email" />
        <f:ajax event="change" execute="@this" />
    </h:inputText>

    <h:inputSecret value="#{loginWEB.user.senha}" autocomplete="off" >
        <f:passThroughAttribute name="placeholder" value="Senha" />
        <f:ajax event="change" execute="@this" />
    </h:inputSecret>

    <h:commandButton id="btn_login" value="Login" action="#{loginWEB.login()}" >
        <f:passThroughAttribute name="data-theme" value="g" />
        <f:ajax render="message" />
    </h:commandButton>
</h:form>

С этим методом действия:

public void login() {
    try {

        FacesContext context = FacesContext.getCurrentInstance();

        if (...) { //Verify email and password
            context.getExternalContext().redirect("/templates/main.xhtml"); 
        }
        else {
            FacesMessage message = new FacesMessage("Invalid email or password");
            message.setSeverity(FacesMessage.SEVERITY_ERROR);
            context.addMessage(null, message);
        }

    } catch (Exception e) {
        Logger.getLogger(LoginWEB.class.getName()).log(Level.SEVERE, null, e);
    }
}

Отправка этой формы иногда вызывает ошибку JS:

httpError: Http Transport вернул 0 код состояния. Обычно это результат смешивания ajax и полных запросов. Обычно это нежелательно по причинам как производительности, так и целостности данных.

Я не понимаю, что я делаю не так. Как это вызвано и как я могу решить это?

3 ответа

Решение

Наконец я нашел реальную проблему.

После проверки и перед перенаправлением я включил некоторые переменные в свой сеанс. Но я составлял список объектов, и это занимало много времени.

Вероятно, jsf все еще ждал возврата, чтобы выполнить запрос ajax, и, прежде чем закончить, я обновлял страницу, вызывая ошибку.

Я удалил его, и теперь все снова хорошо ^^

Большое спасибо @BalusC и @bhdrk за то, что показали мне правильный подход к использованию.

На эту конкретную ошибку действительно есть шанс, если одно из полей ввода все еще находится в фокусе, пока оно изменяется, и кнопка отправки нажимается мышью или клавишей [ввод] вместо того, чтобы вкладываться в нее (так, чтобы сначала происходило событие изменения поля ввода). Состояние гонки будет возникать между 2 запросами Ajax: один вызван событием изменения поля ввода, а другой - событием действия кнопки отправки. В такой ситуации не определено, кто из них первым попадет на сервер.

В JSF запросы ajax ставятся в очередь. Таким образом, если один из них попадет на сервер, другой будет ждать, пока он не вернется и не завершится. Ваша проблема возникнет, когда ajax-запрос кнопки отправки будет первым, который попадет на сервер. В случае успешного входа в систему сервер вернет инструкцию для выполнения перенаправления. Это перенаправление обрабатывается JavaScript во время выполнения запроса ajax. После этого будет запущен следующий запрос ajax в очереди, если таковой имеется (несмотря на перенаправление! Которое, в свою очередь, является IMO, является ошибкой проектирования в движке ajax JSF, но это в стороне). Однако, поскольку документ был изменен путем перенаправления, второй запрос Ajax пропускает попадание, вызывая эту ошибку.

В целом, этот подход к AJAX-формам несколько странен. Поля ввода и кнопка отправки по отдельности отправляют свои значения с помощью ajax, а не все сразу через кнопку отправки. Похоже, что у вас изначально было <f:ajax> в кнопке отправки, но вы решили, что входные значения не были обработаны, поэтому вы решили добавить еще один <f:ajax> в эти поля ввода.

Это не совсем правильный подход. Вы должны использовать execute="@form" в кнопке отправки, чтобы дать команду выполнить (обработать) всю форму.

Итак, так:

<h:form id="f_login">
    <f:passThroughAttribute name="data-ajax" value="false" />

    <h:messages id="message" showDetail="false" errorClass="error_msg" fatalClass="success_msg" infoClass="info_msg" warnClass="warning_msg" />

    <h:inputText value="#{loginWEB.user.email}">
        <f:passThroughAttribute name="placeholder" value="Email" />
    </h:inputText>

    <h:inputSecret value="#{loginWEB.user.senha}" autocomplete="off">
        <f:passThroughAttribute name="placeholder" value="Senha" />
    </h:inputSecret>

    <h:commandButton id="btn_login" value="Login" action="#{loginWEB.login}">
        <f:passThroughAttribute name="data-theme" value="g" />
        <f:ajax execute="@form" render="message" />
    </h:commandButton>
</h:form>

Таким образом, только один запрос ajax будет запущен одновременно, что устраняет риск для условий гонки.

Просто добавьте execute="@form" в это должно работать.

<h:commandButton id="btn_login" value="Login" action="#{loginWEB.login()}" >
    <f:passThroughAttribute name="data-theme" value="g" />
    <f:ajax execute="@form" render="message" />
</h:commandButton>
Другие вопросы по тегам