commandButton/commandLink/ajax действие / метод слушателя не вызван или входное значение не установлено / обновлено

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

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

13 ответов

Решение

Вступление

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

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

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

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

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

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

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

  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 а также UICommand представляющие интерес компоненты охватываются <f:ajax execute> или например <p:commandXxx process> иначе они не будут выполнены / обработаны. См. Также Отправленные значения формы, не обновленные в модели, при добавлении в ; и Понимании процесса / обновления PrimeFaces и атрибутов выполнения / рендеринга JSF f:ajax.

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

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

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

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

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

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

  16. Если вы используете PrimeFaces p:dialog или p:overlayPanel, убедитесь, что вы не столкнетесь с действием p: commandbutton внутри p: не работает

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

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

консоль js

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

сетевой монитор

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

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

сервер отладки

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Помещение этого атрибута в ту же область, что и сами данные таблицы, решило проблему.

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

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

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

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

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

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

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

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

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

Это решение, которое у меня сработало.

<p:commandButton id="b1" value="Save" process="userGroupSetupForm"
                    actionListener="#{userGroupSetupController.saveData()}" 
                    update="growl userGroupList userGroupSetupForm" />

Здесь атрибут process="userGroupSetupForm" является обязательным для вызова Ajax. actionListener вызывает метод из @ViewScope Bean. Также обновляется сообщение рычания, Datatable: userGroupList и Form: userGroupSetupForm.

Решение, которое сработало для меня, заключалось в помещении <p:commandButton> внутри формы или внутри места, где находятся данные формы, скажем, например, в <p:outputPanel>.

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

<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>
<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>
Другие вопросы по тегам