CommandButton / CommandLink / ajax-действие / метод прослушивателя не вызван или входное значение не установлено / обновлено

StackOverflow https://stackoverflow.com/questions/2118656

Вопрос

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

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

Это было полезно?

Решение

Введение

Всякий раз, когда 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>

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

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

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

  2. Вы не можете вложить несколько UIForm компоненты друг в друге.Это незаконно в HTML.Поведение браузера не определено.Будьте осторожны с включаемыми файлами!Вы можете использовать UIForm компоненты работают параллельно, но они не будут обрабатывать друг друга во время отправки.Вам также следует быть осторожным с антипаттерном "Форма бога";убедитесь, что вы непреднамеренно не обрабатываете / не проверяете все другие (невидимые) входные данные в той же форме (напримерналичие скрытого диалогового окна с требуемыми входными данными в той же форме).Смотрите также Как использовать <h:form> на странице 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 из компонента (и, следовательно, не в методе getter!) следует исправить это.Смотрите также Как и когда я должен загрузить модель из базы данных для h:DataTable.

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

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

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

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

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

  10. Если представленные значения по-прежнему оказываются равными null, и вы используете CDI для управления компонентами, затем убедитесь, что вы импортируете аннотацию области из правильного пакета, иначе CDI по умолчанию будет иметь значение @Dependent который эффективно воссоздает компонент при каждом отдельном вычислении выражения EL.Смотрите также компонент @SessionScoped теряет область видимости и постоянно воссоздается заново, поля становятся нулевыми и Какова область управляемого компонента по умолчанию в приложении 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 или что фильтр сервлетов, который отвечает за анализ запросов с составными частями / данными формы, правильно настроен, в противном случае FacesServlet в конечном итоге вы вообще не получите параметров запроса и, следовательно, не сможете применить значения запроса.Способ настройки такого фильтра зависит от используемого компонента загрузки файла.Для Томагавка <t:inputFileUpload>, проверить этот ответ и для первичных лиц <p:fileUpload>, проверить этот ответ.Или, если вы на самом деле вообще не загружаете файл, то вообще удалите атрибут.

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

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

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

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

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

Подсказки по отладке

На случай, если у вас все еще заедает, пришло время отлаживать.На стороне клиента нажмите F12 в webbrowser, чтобы открыть набор инструментов веб-разработчика.Нажмите на кнопку Консоль вкладка, так что смотрите обзор 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-запросов, подобных приведенным выше, из производственной среды, убедитесь, что вы скремблируете / затемняете все сеансовые файлы cookie на скриншоте, чтобы избежать атак с перехватом сеанса!)

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

debug server

Другие советы

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

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

Таким образом, если базовый источник данных ограничен областью запроса, h:commandLink не работает!

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

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

Как указано в Руководстве пользователя PrimeFaces в разделе 3.18, значения по умолчанию для 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.

У меня была командная кнопка в строке таблицы данных (расширенная версия, поэтому <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, а также bean-компоненты, выполняющие представления моего приложения и бизнес-логику.

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

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

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

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

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

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

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

<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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top