Ответ 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 +, чтобы открыть набор инструментов веб-разработчика, а затем откройте вкладку "Консоль"), затем просмотрите приведенный ниже список возможных причин.,
Возможные причины
-
UICommand
иUIInput
должны быть размещены внутри компонентаUIForm
, например,<h:form>
(и, следовательно, не в виде простого HTML<form>
), иначе на сервер ничего нельзя отправить. КомпонентыUICommand
также не должны иметь атрибутtype="button"
, иначе это будет мертвая кнопка, которая полезна только для JavaScript приonclick
. Смотрите также Как отправить входные значения формы и вызвать метод в bean-компоненте JSF, и <h: commandButton> не инициирует обратную передачу. -
Вы не можете
UIForm
несколько компонентовUIForm
друг в друга. Это незаконно в HTML. Поведение браузера не определено. Остерегайтесь включаемых файлов! Вы можете использовать компонентыUIForm
параллельно, но они не будут обрабатывать друг друга во время отправки. Вы также должны остерегаться "антипаттерна формы Бога"; убедитесь, что вы непреднамеренно не обрабатываете/не проверяете все другие (невидимые) входные данные в той же форме (например, наличие скрытого диалога с необходимыми входными данными в той же форме). Смотрите также Как использовать <h: form> на странице JSF? Одиночная форма? Несколько форм? Вложенные формы? , -
UIInput
проверки/преобразования значенияUIInput
должна была возникнуть. Вы можете использовать<h:messages>
для отображения любых сообщений, которые не отображаются никакими компонентами<h:message>
специфичными для ввода. Не забудьте включитьid
<h:messages>
в<f:ajax render>
, если таковой имеется, чтобы он также обновлялся при запросах ajax. См. Также h: messages не отображает сообщения при нажатии кнопки p: commandButton. -
Если компоненты
UICommand
илиUIInput
находятся внутриUIInput
компонента, такого как<h:dataTable>
,<ui:repeat>
и т.д.,<h:dataTable>
необходимо убедиться, что на этапе применения значений запроса применяется одно и то жеvalue
итерационного компонента. Форма отправки запроса. JSF будет повторять его, чтобы найти нажатую ссылку/кнопку и ввести введенные значения. Помещение компонента в область видимости и/или@PostConstruct
загрузки модели данных в@PostConstruct
компонента (и, следовательно, не в методе получения!) Должны исправить это. Смотрите также Как и когда я должен загрузить модель из базы данных для h: dataTable. -
Если компоненты
UICommand
илиUIInput
включены динамическим источником, таким как<ui:include src="#{bean.include}">
, то необходимо убедиться, что во время просмотра сохраняется точно такое же значение#{bean.include}
Время сборки формы отправить запрос. JSF повторно выполнит его во время построения дерева компонентов. Помещение компонента в область видимости и/или@PostConstruct
загрузки модели данных в@PostConstruct
компонента (и, следовательно, не в методе получения!) Должны исправить это. См. Также Как ajax-refresh динамически включать контент с помощью меню навигации? (JSF SPA). -
rendered
атрибут компонента и все его родителей иtest
атрибут любого родителя<c:if>
/<c:when>
не следуют оценивать поfalse
во время запроса применяется значение фазы подчиненной формы запроса. JSF будет перепроверять его как часть защиты от подделанных/взломанных запросов. Хранение переменных, отвечающих за условие, в компоненте@ViewScoped
или@ViewScoped
правильности предварительной@PostConstruct
условия в@PostConstruct
компонента@RequestScoped
должны исправить это. То же самое относится и кdisabled
атрибуту компонента, который не должен иметь значениеtrue
во время фазы применения значений запроса. См. Также действие JSF CommandButton, которое не вызывается, и отправка формы в условно отображаемом компоненте не обрабатывается. -
onclick
атрибутUICommand
компонента иonsubmit
атрибутUIForm
компоненты не должен возвращатьfalse
или вызвать ошибку JavaScript. В случае<h:commandLink>
или<f:ajax>
также не должно быть никаких ошибок JS, видимых в консоли JS браузера. Обычно поиск точного сообщения об ошибке уже даст вам ответ. Смотрите также Добавление jQuery в PrimeFaces приводит к Uncaught TypeErrors. -
Если вы используете 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. -
Если вы используете Ajax, и отправленные значения в конечном итоге
UIInput
null
, то убедитесь, что представляющиеUIInput
компонентыUIInput
иUICommand
охвачены<f:ajax execute>
или, например,<p:commandXxx process>
, иначе они<p:commandXxx process>
' быть выполненным/обработанным. См. Также Отправленные значения формы, не обновленные в модели, при добавлении <f: ajax> в <h: commandButton> и Понимании процесса/обновления PrimeFaces и атрибутов выполнения/рендеринга JSF f: ajax. -
Если отправленные значения все равно оказываются
null
, и вы используете CDI для управления bean-компонентами, убедитесь, что вы импортируете аннотацию области действия из правильного пакета, иначе CDI по умолчанию будет иметь значение@Dependent
которое эффективно воссоздает bean-компонент при каждой отдельной оценке. выражения EL. См. Также @SessionScoped bean-компонент теряет область видимости и постоянно воссоздается, поля становятся пустыми и какова область действия управляемого компонента по умолчанию в приложении JSF 2? -
Если родительский элемент
<h:form>
с кнопкойUICommand
был предварительно обработан/обновлен с помощью ajax-запроса, поступающего из другой формы на той же странице, то первое действие всегда будет неудачным в JSF 2.2 или более ранней версии. Второе и последующие действия будут работать. Это вызвано ошибкой в обработке состояния представления, которая сообщается как проблема спецификации JSF 790 и в настоящее время исправлена в JSF 2.3. Для более старых версий JSF вам необходимо явно указать идентификатор<h:form>
вrender
<f:ajax>
. См. Также h: commandButton/h: commandLink не работает при первом щелчке, работает только при втором щелчке. -
Если для
<h:form>
установлено значениеenctype="multipart/form-data"
для поддержки загрузки файлов, вам необходимо убедиться, что вы используете хотя бы JSF 2.2 или что фильтр сервлетов, который отвечает за синтаксический анализ запросов multipart/form-data настроен правильно, в противном случаеFacesServlet
итоге не получит параметров запроса вообще и, следовательно, не сможет применить значения запроса. Как настроить такой фильтр, зависит от используемого компонента загрузки файла. Для Tomahawk<t:inputFileUpload>
проверьте этот ответ, а для PrimeFaces<p:fileUpload>
проверьте этот ответ. Или, если вы вообще не загружаете файл, удалите атрибут вообще. -
Убедитесь, что аргумент
ActionEvent
дляactionListener
являетсяjavax.faces.event.ActionEvent
и, следовательно, неjava.awt.event.ActionEvent
, что большинство IDE предлагают в качестве первого параметра автозаполнения. Иметь аргументы без аргументов также неправильно, если вы используетеactionListener="#{bean.method}"
. Если вам не нужен аргумент в вашем методе, используйтеactionListener="#{bean.method()}"
. Или, возможно, вы действительно хотите использоватьaction
вместоactionListener
. Смотрите также Различия между action и actionListener. -
Убедитесь, что ни один
PhaseListener
ни какой-либоEventListener
вEventListener
запрос-ответ не изменили жизненный цикл JSF для пропуска фазы действия вызова, например, путем вызоваFacesContext#renderResponse()
илиFacesContext#responseComplete()
. -
Убедитесь, что ни один
Filter
илиServlet
в той же цепочке запрос-ответ каким-FacesServlet
образом не заблокировал запросFacesServlet
. -
Если вы используете PrimeFaces
<p:dialog>
или<p:overlayPanel>
, убедитесь, что у них есть собственная<h:form>
. Потому что по умолчанию эти компоненты перемещены в конец HTML<body>
. Итак, если бы они изначально сидели внутри<form>
, то теперь они больше не сидели бы в<form>
. См. Также действие p: commandbutton внутри p: не работает -
Ошибка в рамках. Например, RichFaces имеет " ошибку преобразования " при использовании элемента пользовательского интерфейса
rich:calendar
с атрибутомdefaultLabel
(или, в некоторых случаях, подэлементомrich:placeholder
). Эта ошибка предотвращает вызов метода bean, если для календарной даты не задано значение. Отследить ошибки в фреймворке можно, начав с простого рабочего примера и создавая страницу обратно, пока ошибка не будет обнаружена.
Советы по отладке
Если вы все еще застряли, пришло время отладки. На стороне клиента нажмите F12 в веб-браузере, чтобы открыть набор инструментов для веб-разработчиков. Перейдите на вкладку "Консоль", чтобы увидеть JavaScript. Он не должен содержать ошибок JavaScript. Ниже на скриншоте показан пример из Chrome, который демонстрирует случай отправки кнопки с включенным <f:ajax>
без объявления <h:head>
(как описано в пункте 7 выше).
Нажмите вкладку Сеть, чтобы увидеть монитор трафика HTTP. Отправьте форму и выясните, соответствуют ли заголовки запроса, данные формы и тело ответа ожиданиям. Ниже на скриншоте показан пример из Chrome, который демонстрирует успешную отправку ajax простой формы с одним <h:inputText>
и одним <h:commandButton>
с <f:ajax execute="@form" render="@form">
(предупреждение: когда вы публикуете скриншоты из заголовков HTTP-запросов, как указано выше, из продакшен среды, убедитесь, что вы зашифровываете/скрываете любые сессионные куки файлы на снимке экрана, чтобы избежать атак захвата сессии!)
На стороне сервера убедитесь, что сервер запущен в режиме отладки. Поместите точку останова отладки в метод интересующего компонента JSF, который вы ожидаете вызвать во время обработки отправки формы. Например, в случае компонента UICommand
это будет UICommand#queueEvent()
а в случае компонента UIInput
это будет UIInput#validate()
. Просто выполните выполнение кода и проверьте, соответствуют ли поток и переменные ожиданиям. Ниже на скриншоте приведен пример отладчика Eclipse.