Очередь событий JSF ajax не работает с событием действия после события изменения

Поддерживаемая функция JSF 2.x последовательной обработки нескольких ajax-событий у меня не работает. Получился такой сценарий:

  1. h: inputText (ИЗМЕНИТЬ)

    <h:inputText id="consumption_input"
       value="#{cc.attrs.consumptionInfo.consumption}">
      <f:ajax
         render="#{cc.attrs.outerRenderString}"
         event="change" listener="#{cc.handleAjaxRequest}" />
    </h:inputText>
    
  2. h: commandButton (ДЕЙСТВИЕ)

    <h:commandButton
        id="startComparisonButton"
        action="#{rateComparisonBean.startRateComparison()}"
        value="#{bundle.rateResultOverview_startComparison}">
        <!-- This is to avoid mixed requests, ajax and full requests -->
           <f:ajax render="@form"/>
        </h:commandButton>
    

События обоих элементов обрабатываются правильно, если запускаются сами по себе.

Проблема возникает, когда оба события запускаются в течение одного щелчка (введите значение в textInput, а затем нажмите кнопку). Я ожидал, что это приведет к синхронному запуску двух запросов ajax (CHANGE-TextField и ACTION-commandButton).

К сожалению, есть только один Ajax-Request (Change-TextField), второе событие, похоже, полностью потеряно.

Я уже убедился, что все предварительные условия для ah: commandButton полностью заполнены, как указано здесь: commandButton / commandLink / ajax метод действия / слушателя не вызван или входное значение не обновлено

Буду признателен за любые подсказки о том, как решить эту проблему.

Окружающая среда: Glassfish 3, Mojarra 2.1.3-FCS


person Mischa Höchsmann    schedule 03.05.2013    source источник
comment
Интересно ... Вы проверили это в небольшом легко реплицируемом приложении? Можно ли заменить Mojarra на MyFaces и посмотреть, будет ли у вас такое же поведение?   -  person maple_shaft    schedule 03.05.2013
comment
Вы когда-нибудь сталкивались с ожидаемым поведением с двумя активированными слушателями (действия)?   -  person skuntsel    schedule 03.05.2013
comment
Вы нашли решение? Я столкнулся с той же проблемой.   -  person Shady Hussein    schedule 17.11.2014


Ответы (2)


Вызовы JSF AJAX асинхронны. Отправка одного запроса AJAX, в данном случае сгенерированного событием <h:inputText> onchange, не останавливает JavaScipt для продолжения его выполнения и, в этом случае, вызывает нажатие кнопки отправки, что, в свою очередь, запускает другой запрос AJAX. Тем не менее, запросы AJAX действительно помещаются в очередь на клиенте для обработки в точном порядке, в котором они были отправлены, что гарантируется Спецификация JSF 2.0, глава 13.3.2.

Ниже мой тестовый пример:

Вид:

<h:form id="form">
    <h:inputText id="text" value="#{q16363737Bean.text1}">
        <f:ajax render="text2" event="change" listener="#{q16363737Bean.ajaxListenerText}"/>
    </h:inputText>
    <h:commandButton id="button" action="#{q16363737Bean.actionButton}" value="Submit">
        <f:ajax render="text1 text3" listener="#{q16363737Bean.ajaxListenerButton}"/>
    </h:commandButton>
    <br/>
    <h:outputText id="text1" value="Text 1: #{q16363737Bean.text1}."/>
    <h:outputText id="text2" value="Text 2: #{q16363737Bean.text2}."/>
    <h:outputText id="text3" value="Text 3: #{q16363737Bean.text3}."/>
</h:form>

Боб:

@ManagedBean
@ViewScoped
public class Q16363737Bean implements Serializable {

    private String text1 = "I'm text 1";//getter + setter
    private String text2 = "I'm text 2";//getter + setter
    private String text3 = "I'm text 3";//getter + setter

    public void ajaxListenerText(AjaxBehaviorEvent abe) {
        text2 = "I was modified after inputText AJAX call";
    }

    public void ajaxListenerButton(AjaxBehaviorEvent abe) {
        text1 = "I was modified after AJAX listener call of commandButton";
    }

    public void actionButton() {
        text3 = "I was modified after commandButton AJAX call";
    }

}

Изучив вопрос в течение некоторого времени, я действительно понял, что очень редко вызов AJAX командной кнопки был проглочен и никаких обновлений пользовательского интерфейса не производилось. Похоже, что где-то должны быть какие-то гоночные условия. Это отличный вопрос, и его нужно исследовать дальше.

Так что, вероятно, это не ответ (хотя я думал, что это будет изначально), а предложение для тестового примера. И несмотря на то, что я сталкивался с таким поведением очень редко, это реальный вариант использования, и стоит полностью понять, что происходит.

person skuntsel    schedule 03.05.2013

Прежде всего, спасибо за быстрый и подробный ответ.

Второй тест с нуля показал, что ajax-события правильно ставятся в очередь.

Итак, я снова проверил более сложный сценарий, описанный выше. Причина пропущенных швов событий связана с нашим «занятым оверлеем». Думайте об этом как о связке JavaScript, который отключает элементы формы и применяет оверлей во время длительных запросов ajax. Для этого используется обратный вызов jsf.ajax.addOnEvent.

В любом случае, даже если мы отключим некоторые элементы управления, после «успеха» форма будет в правильном состоянии, и второе событие может быть обработано.

В настоящее время я предполагаю, что «временно» отключенная кнопка ставит под угрозу соответствующее событие действия, которое должно быть выполнено впоследствии.

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

person Mischa Höchsmann    schedule 03.05.2013
comment
Вы нашли решение? Я знаю, что это было опубликовано совсем недавно, но я столкнулся с той же проблемой. Я не могу найти решение, не удалив занятый оверлей или не поставив на него задержку. - person Mitchell Brooks; 27.12.2017
comment
К сожалению, нет, и бизнес, ради которого мы хотели его вести, больше не существует. Но дело не только в накладке :-) - person Mischa Höchsmann; 15.06.2019