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>