CommandButton/commandLink/ajax action/listener метод не вызывается или входное значение не установлено/обновлено

Иногда при использовании <h:commandLink>, <h:commandButton> или <f:ajax> метод action, actionListener или listener, связанный с тегом, просто не вызывается. Или, свойства bean не обновляются с представленными значениями UIInput.

Каковы возможные причины и решения для этого?

Ответ 1

Вступление

Всякий раз, когда компонент UICommand (<h:commandXxx>, <p:commandXxx> и т.д.) Не может вызвать связанный метод действия, или компонент UIInput (<h:inputXxx>, <p:inputXxxx> и т.д.) Не может обработать отправленные значения и/или обновите значения модели, и вы не увидите никаких исключений и/или предупреждений, связанных с googlable, в журнале сервера, в том числе при настройке обработчика исключений ajax в соответствии с обработкой исключений в запросах ajax JSF или при установке под контекстным параметром в web.xml,

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

вы также не видите никаких ошибок и/или предупреждений, связанных с Google, в консоли браузера JavaScript (нажмите F12 в Chrome/Firefox23+/IE9 +, чтобы открыть набор инструментов веб-разработчика, а затем откройте вкладку "Консоль"), затем просмотрите приведенный ниже список возможных причин.,

Возможные причины

  1. UICommand и UIInput должны быть размещены внутри компонента UIForm, например, <h:form> (и, следовательно, не в виде простого HTML <form>), иначе на сервер ничего нельзя отправить. Компоненты UICommand также не должны иметь атрибут type="button", иначе это будет мертвая кнопка, которая полезна только для JavaScript при onclick. Смотрите также Как отправить входные значения формы и вызвать метод в bean-компоненте JSF, и <h: commandButton> не инициирует обратную передачу.

  2. Вы не можете UIForm несколько компонентов UIForm друг в друга. Это незаконно в HTML. Поведение браузера не определено. Остерегайтесь включаемых файлов! Вы можете использовать компоненты UIForm параллельно, но они не будут обрабатывать друг друга во время отправки. Вы также должны остерегаться "антипаттерна формы Бога"; убедитесь, что вы непреднамеренно не обрабатываете/не проверяете все другие (невидимые) входные данные в той же форме (например, наличие скрытого диалога с необходимыми входными данными в той же форме). Смотрите также Как использовать <h: form> на странице JSF? Одиночная форма? Несколько форм? Вложенные формы? ,

  3. UIInput проверки/преобразования значения UIInput должна была возникнуть. Вы можете использовать <h:messages> для отображения любых сообщений, которые не отображаются никакими компонентами <h:message> специфичными для ввода. Не забудьте включить id <h:messages> в <f:ajax render>, если таковой имеется, чтобы он также обновлялся при запросах ajax. См. Также h: messages не отображает сообщения при нажатии кнопки p: commandButton.

  4. Если компоненты UICommand или UIInput находятся внутри UIInput компонента, такого как <h:dataTable>, <ui:repeat> и т.д., <h:dataTable> необходимо убедиться, что на этапе применения значений запроса применяется одно и то же value итерационного компонента. Форма отправки запроса. JSF будет повторять его, чтобы найти нажатую ссылку/кнопку и ввести введенные значения. Помещение компонента в область видимости и/или @PostConstruct загрузки модели данных в @PostConstruct компонента (и, следовательно, не в методе получения!) Должны исправить это. Смотрите также Как и когда я должен загрузить модель из базы данных для h: dataTable.

  5. Если компоненты UICommand или UIInput включены динамическим источником, таким как <ui:include src="#{bean.include}">, то необходимо убедиться, что во время просмотра сохраняется точно такое же значение #{bean.include} Время сборки формы отправить запрос. JSF повторно выполнит его во время построения дерева компонентов. Помещение компонента в область видимости и/или @PostConstruct загрузки модели данных в @PostConstruct компонента (и, следовательно, не в методе получения!) Должны исправить это. См. Также Как ajax-refresh динамически включать контент с помощью меню навигации? (JSF SPA).

  6. rendered атрибут компонента и все его родителей и test атрибут любого родителя <c:if>/<c:when> не следуют оценивать по false во время запроса применяется значение фазы подчиненной формы запроса. JSF будет перепроверять его как часть защиты от подделанных/взломанных запросов. Хранение переменных, отвечающих за условие, в компоненте @ViewScoped или @ViewScoped правильности предварительной @PostConstruct условия в @PostConstruct компонента @RequestScoped должны исправить это. То же самое относится и к disabled атрибуту компонента, который не должен иметь значение true во время фазы применения значений запроса. См. Также действие JSF CommandButton, которое не вызывается, и отправка формы в условно отображаемом компоненте не обрабатывается.

  7. onclick атрибут UICommand компонента и onsubmit атрибут UIForm компоненты не должен возвращать false или вызвать ошибку JavaScript. В случае <h:commandLink> или <f:ajax> также не должно быть никаких ошибок JS, видимых в консоли JS браузера. Обычно поиск точного сообщения об ошибке уже даст вам ответ. Смотрите также Добавление jQuery в PrimeFaces приводит к Uncaught TypeErrors.

  8. Если вы используете Ajax через JSF 2.x <f:ajax> или, например, PrimeFaces <p:commandXxx>, убедитесь, что у вас есть <h:head> в главном шаблоне вместо <head>. В противном случае JSF не сможет автоматически включать необходимые файлы JavaScript, которые содержат функции Ajax. Это может привести к ошибке JavaScript, такой как "mojarra не определен" или "PrimeFaces не определен" в консоли JS браузера. Смотрите также h: commandLink actionlistener не вызывается при использовании с f: ajax и ui: repeat.

  9. Если вы используете Ajax, и отправленные значения в конечном итоге UIInput null, то убедитесь, что представляющие UIInput компоненты UIInput и UICommand охвачены <f:ajax execute> или, например, <p:commandXxx process>, иначе они <p:commandXxx process> ' быть выполненным/обработанным. См. Также Отправленные значения формы, не обновленные в модели, при добавлении <f: ajax> в <h: commandButton> и Понимании процесса/обновления PrimeFaces и атрибутов выполнения/рендеринга JSF f: ajax.

  10. Если отправленные значения все равно оказываются null, и вы используете CDI для управления bean-компонентами, убедитесь, что вы импортируете аннотацию области действия из правильного пакета, иначе CDI по умолчанию будет иметь значение @Dependent которое эффективно воссоздает bean-компонент при каждой отдельной оценке. выражения EL. См. Также @SessionScoped bean-компонент теряет область видимости и постоянно воссоздается, поля становятся пустыми и какова область действия управляемого компонента по умолчанию в приложении JSF 2?

  11. Если родительский элемент <h:form> с кнопкой UICommand был предварительно обработан/обновлен с помощью ajax-запроса, поступающего из другой формы на той же странице, то первое действие всегда будет неудачным в JSF 2.2 или более ранней версии. Второе и последующие действия будут работать. Это вызвано ошибкой в обработке состояния представления, которая сообщается как проблема спецификации JSF 790 и в настоящее время исправлена в JSF 2.3. Для более старых версий JSF вам необходимо явно указать идентификатор <h:form> в render <f:ajax>. См. Также h: commandButton/h: commandLink не работает при первом щелчке, работает только при втором щелчке.

  12. Если для <h:form> установлено значение enctype="multipart/form-data" для поддержки загрузки файлов, вам необходимо убедиться, что вы используете хотя бы JSF 2.2 или что фильтр сервлетов, который отвечает за синтаксический анализ запросов multipart/form-data настроен правильно, в противном случае FacesServlet итоге не получит параметров запроса вообще и, следовательно, не сможет применить значения запроса. Как настроить такой фильтр, зависит от используемого компонента загрузки файла. Для Tomahawk <t:inputFileUpload> проверьте этот ответ, а для PrimeFaces <p:fileUpload> проверьте этот ответ. Или, если вы вообще не загружаете файл, удалите атрибут вообще.

  13. Убедитесь, что аргумент ActionEvent для actionListener является javax.faces.event.ActionEvent и, следовательно, не java.awt.event.ActionEvent, что большинство IDE предлагают в качестве первого параметра автозаполнения. Иметь аргументы без аргументов также неправильно, если вы используете actionListener="#{bean.method}". Если вам не нужен аргумент в вашем методе, используйте actionListener="#{bean.method()}". Или, возможно, вы действительно хотите использовать action вместо actionListener. Смотрите также Различия между action и actionListener.

  14. Убедитесь, что ни один PhaseListener ни какой-либо EventListener в EventListener запрос-ответ не изменили жизненный цикл JSF для пропуска фазы действия вызова, например, путем вызова FacesContext#renderResponse() или FacesContext#responseComplete().

  15. Убедитесь, что ни один Filter или Servlet в той же цепочке запрос-ответ каким- FacesServlet образом не заблокировал запрос FacesServlet.

  16. Если вы используете PrimeFaces <p:dialog> или <p:overlayPanel>, убедитесь, что у них есть собственная <h:form>. Потому что по умолчанию эти компоненты перемещены в конец HTML <body>. Итак, если бы они изначально сидели внутри <form>, то теперь они больше не сидели бы в <form>. См. Также действие p: commandbutton внутри p: не работает

  17. Ошибка в рамках. Например, RichFaces имеет " ошибку преобразования " при использовании элемента пользовательского интерфейса rich:calendar с атрибутом defaultLabel (или, в некоторых случаях, подэлементом rich:placeholder). Эта ошибка предотвращает вызов метода bean, если для календарной даты не задано значение. Отследить ошибки в фреймворке можно, начав с простого рабочего примера и создавая страницу обратно, пока ошибка не будет обнаружена.

Советы по отладке

Если вы все еще застряли, пришло время отладки. На стороне клиента нажмите F12 в веб-браузере, чтобы открыть набор инструментов для веб-разработчиков. Перейдите на вкладку "Консоль", чтобы увидеть JavaScript. Он не должен содержать ошибок JavaScript. Ниже на скриншоте показан пример из Chrome, который демонстрирует случай отправки кнопки с включенным <f:ajax> без объявления <h:head> (как описано в пункте 7 выше).

js console

Нажмите вкладку Сеть, чтобы увидеть монитор трафика HTTP. Отправьте форму и выясните, соответствуют ли заголовки запроса, данные формы и тело ответа ожиданиям. Ниже на скриншоте показан пример из Chrome, который демонстрирует успешную отправку ajax простой формы с одним <h:inputText> и одним <h:commandButton> с <f:ajax execute="@form" render="@form">

network monitor

(предупреждение: когда вы публикуете скриншоты из заголовков HTTP-запросов, как указано выше, из продакшен среды, убедитесь, что вы зашифровываете/скрываете любые сессионные куки файлы на снимке экрана, чтобы избежать атак захвата сессии!)

На стороне сервера убедитесь, что сервер запущен в режиме отладки. Поместите точку останова отладки в метод интересующего компонента JSF, который вы ожидаете вызвать во время обработки отправки формы. Например, в случае компонента UICommand это будет UICommand#queueEvent() а в случае компонента UIInput это будет UIInput#validate(). Просто выполните выполнение кода и проверьте, соответствуют ли поток и переменные ожиданиям. Ниже на скриншоте приведен пример отладчика Eclipse.

debug server

Ответ 2

Если ваш h:commandLink находится внутри h:dataTable есть еще одна причина, по которой h:commandLink может не работать:

Базовый источник данных, связанный с h:dataTable также должен быть доступен во втором жизненном h:dataTable JSF, который запускается при щелчке по ссылке.

Поэтому, если базовый источник данных находится в области запроса, h:commandLink не работает!

Ответ 3

Хотя мой ответ не применим на 100%, но большинство поисковых систем считают это первым хитом, я решил опубликовать его без изменений:

Если вы используете PrimeFaces (или какой-либо аналогичный API) p:commandButton или p:commandLink, скорее всего, вы забыли явно добавить process="@this" в свои компоненты команды.

Как указано в руководстве пользователя PrimeFaces в разделе 3.18, значения по умолчанию для process и update равны @form, что в значительной степени противоречит значениям по умолчанию, которые вы можете ожидать от простого JSF f:ajax или RichFaces, которые execute="@this" и render="@none" соответственно.

Просто я нашел время, чтобы узнать. (... и я думаю, что это довольно нечисто для использования значений по умолчанию, отличных от JSF!)

Ответ 4

Я бы упомянул еще одну вещь, касающуюся Primefaces p:commandButton!

Когда вы используете p:commandButton для действия, которое необходимо выполнить на сервере, вы не можете использовать type="button", потому что это для кнопок, которые используются для выполнения пользовательского javascript без вызывая запрос ajax/non-ajax на сервер.

С этой целью вы можете распределить атрибут type (значение по умолчанию "submit") или вы можете явно использовать type="submit".

Надеюсь, это поможет кому-то!

Ответ 5

Я сам застрял в этой проблеме и нашел еще одну причину этой проблемы. Если у вас нет методов setter в вашей поддержке bean для свойств, используемых в вашем *.xhtml, тогда действие просто не вызывается.

Ответ 6

Недавно я столкнулся с проблемой, когда UICommand не вызывался в приложении JSF 1.2 с использованием компонентов IBM Extended Faces.

У меня была кнопка команды в строке datatable (расширенная версия, поэтому <hx:datatable>), и UICommand не запускал из определенных строк из таблицы (строки, которые не запускались бы, были строками, превышающими значения по умолчанию размер отображения строки).

У меня был раскрывающийся компонент для выбора количества строк для отображения. Значение, поддерживающее это поле, находилось в RequestScope. Данные, хранящиеся в самой таблице, были в виде ViewScope (на самом деле, временно в SessionScope).

Если отображение строки было увеличено с помощью элемента управления, значение которого также было привязано к атрибуту datatable rows, ни одна из строк, отображаемых в результате этого изменения, не могла запустить UICommand при нажатии.

Размещение этого атрибута в той же области, что и сама таблица данных. Это проблема.

Я думаю, что это упоминается в BalusС# 4 выше, но не только значение таблицы должно быть View или Session scoped, но также атрибут, контролирующий количество строк для отображения в этой таблице.

Ответ 7

У меня тоже была эта проблема, и я действительно начал отталкиваться от основной причины после открытия веб-консоли браузера. До этого я не смог получить никаких сообщений об ошибках (даже с <p:messages>). Веб-консоль показала код статуса HTTP 405, возвращающийся с <h:commandButton type="submit" action="#{myBean.submit}">.

В моем случае у меня есть смесь ванильного HttpServlet, обеспечивающего аутентификацию OAuth через Auth0 и JSF facelets и beans, выполняющие представления приложений и бизнес-логику.

Как только я реорганизовал свой web.xml и удалил сервлет среднего уровня, он тогда "волшебным образом" работал.

В итоге, проблема заключалась в том, что сервлет среднего класса использовал RequestDispatcher.forward(...) для перенаправления из среды HttpServlet в среду JSF, тогда как сервлет, вызываемый до этого, перенаправлялся с помощью HttpServletResponse.sendRedirect(...).

В принципе, использование sendRedirect() разрешало "контейнеру" JSF брать контроль, тогда как RequestDispatcher.forward() явно не был.

Я не знаю, почему facelet смог получить доступ к свойствам bean, но не мог их установить, и это явно кричит о том, что он удаляет смесь сервлетов и JSF, но я надеюсь, что это поможет кому-то избежать много часов головокружительного удара.

Ответ 8

Мне было очень весело отлаживать проблему, когда действие <h:commandLink> в richfaces datatable не срабатывало. Таблица использовалась для работы в какой-то момент, но прекратилась без видимых причин. Я не оставил камня на камне, только чтобы узнать, что мой rich:datatable использовал неправильный rowKeyConverter, который возвращал nulls, которые richfaces счастливо использовались в качестве ключей строки. Это предотвратило получение моего действия <h:commandLink>.

Ответ 9

Еще одна возможность: если симптом заключается в том, что первый вызов работает, но последующих нет, вы можете использовать PrimeFaces 3.x с JSF 2.2, как описано здесь: Нет ViewState отправляется.

Ответ 10

<ui:composition>  
  <h:form id="form1">
    <p:dialog id="dialog1">
      <p:commandButton value="Save" action="#{bean.method1}" /> <!--Working-->
    </p:dialog>
  </h:form>

  <h:form id="form2">
    <p:dialog id="dialog2">
      <p:commandButton value="Save" action="#{bean.method2}" /> <!--Not Working-->
    </p:dialog>
  </h:form>
</ui:composition>

Решать;

<ui:composition>  
  <h:form id="form1">
    <p:dialog id="dialog1">
      <p:commandButton value="Save" action="#{bean.method1}" />   <!-- Working  -->
    </p:dialog>

    <p:dialog id="dialog2">
      <p:commandButton value="Save" action="#{bean.method2}" />   <!--Working  -->
    </p:dialog>
  </h:form>
  <h:form id="form2">
    <!-- ..........  -->
  </h:form>
</ui:composition>

Ответ 11

Я исправил мою проблему с размещением:

<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>

В:

<h:form>
     <h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
</h:form>