有时候,当使用<h:commandLink>
,<h:commandButton>
或<f:ajax>
时,与标签相关的action
,actionListener
或listener
方法根本就没有被调用。或者,bean属性不会使用提交的UIInput
值更新。
有什么可能的原因和解决方案?
每当UICommand
组件(<h:commandXxx>
,<p:commandXxx>
等)无法调用相关的操作方法,或者UIInput
组件(<h:inputXxx>
,<p:inputXxxx>
等)无法处理提交的值和/或更新模型值,并且您没有看到服务器日志中的任何googlable异常和/或警告,当你根据Exception handling in JSF ajax requests配置ajax异常处理程序时,也不是在web.xml
中设置下面的context参数时,
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
并且您也没有在浏览器的JavaScript控制台中看到任何可搜索的错误和/或警告(按Chrome / Firefox23 + / IE9 +中的F12打开Web开发人员工具集,然后打开控制台选项卡),然后查看下面可能的原因列表。
UICommand
和UIInput
组件必须放在UIForm
组件内,例如<h:form>
(因此不是简单的HTML <form>
),否则什么都不能发送到服务器。 UICommand
组件也必须没有type="button"
属性,否则它将是一个死按钮,只对JavaScript onclick
有用。另见How to send form input values and invoke a method in JSF bean和<h:commandButton> does not initiate a postback。UIForm
组件嵌套在一起。这在HTML中是非法的。浏览器行为未指定。注意包含文件!您可以并行使用UIForm
组件,但在提交期间它们不会互相处理。你也应该注意“神形”反模式;确保您不会无意中以相同的形式处理/验证所有其他(不可见)输入(例如,以相同的形式具有所需输入的隐藏对话框)。另见How to use <h:form> in JSF page? Single form? Multiple forms? Nested forms?。UIInput
值验证/转换错误。您可以使用<h:messages>
显示任何特定于输入的<h:message>
组件未显示的消息。不要忘记在id
中加入<h:messages>
的<f:ajax render>
(如果有的话),这样它也会在ajax请求中更新。另见h:messages does not display messages when p:commandButton is pressed。UICommand
或UIInput
组件放在<h:dataTable>
,<ui:repeat>
等迭代组件中,那么您需要确保在表单提交请求的应用请求值阶段保留了与迭代组件完全相同的value
。 JSF将重申它以查找单击的链接/按钮和提交的输入值。将bean放在视图范围中和/或确保在bean的@PostConstruct
中加载数据模型(因此不在getter方法中!)应该修复它。另见How and when should I load the model from database for h:dataTable。UICommand
)包含UIInput
或<ui:include src="#{bean.include}">
组件,则需要确保在表单提交请求的视图构建时间内保留完全相同的#{bean.include}
值。 JSF将在构建组件树期间重新执行它。将bean放在视图范围中和/或确保在bean的@PostConstruct
中加载数据模型(因此不在getter方法中!)应该修复它。另见How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)。rendered
属性以及任何父test
/ <c:if>
的<c:when>
属性在表单提交请求的应用请求值阶段不应评估为false
。 JSF将重新检查它作为防范篡改/黑客攻击请求的一部分。在@ViewScoped
bean中存储负责该条件的变量,或者确保在@PostConstruct
bean的@RequestScoped
中正确预先初始化该条件应该修复它。这同样适用于组件的disabled
属性,在应用请求值阶段不应评估为true
。另见JSF CommandButton action not invoked和Form submit in conditionally rendered component is not processed。onclick
组件的UICommand
属性和onsubmit
组件的UIForm
属性不应返回false
或导致JavaScript错误。在<h:commandLink>
或<f:ajax>
的情况下,在浏览器的JS控制台中也不会出现JS错误。通常谷歌搜索确切的错误信息已经给你答案。另见Adding jQuery to PrimeFaces results in Uncaught TypeError over all place。<f:ajax>
使用Ajax或者例如PrimeFaces <p:commandXxx>
,确保你在主模板中有一个<h:head>
而不是<head>
。否则,JSF将无法自动包含包含Ajax函数的必要JavaScript文件。这将导致JavaScript错误,例如“mojarra未定义”或浏览器的JS控制台中未定义“PrimeFaces”。另见h:commandLink actionlistener is not invoked when used with f:ajax and ui:repeat。UIInput
涵盖的UICommand
和<f:ajax execute>
组件或<p:commandXxx process>
,否则他们将不会被执行/处理。另见Submitted form values not updated in model when adding <f:ajax> to <h:commandButton>和Understanding PrimeFaces process/update and JSF f:ajax execute/render attributes。<h:form>
按钮的UICommand
的父级预先由来自同一页面中的另一个表单的ajax请求呈现/更新,则第一个操作将始终失败。第二个及后续操作将起作用。这是由视图状态处理中的错误引起的,该错误报告为JSF spec issue 790并且当前计划在JSF 2.3中修复。对于较旧的JSF版本,您需要在<h:form>
的render
中明确指定<f:ajax>
的ID。另见h:commandButton/h:commandLink does not work on first click, works only on second click。<h:form>
设置了enctype="multipart/form-data"
以支持文件上载,那么您需要确保至少使用JSF 2.2,或者正确配置负责解析multipart / form-data请求的servlet过滤器,否则FacesServlet
最终将不会获得任何请求参数,因此无法应用请求值。如何配置此类过滤器取决于正在使用的文件上载组件。对于Tomahawk <t:inputFileUpload>
,检查this answer和PrimeFaces <p:fileUpload>
,检查this answer。或者,如果您实际上根本没有上传文件,则完全删除该属性。ActionEvent
的actionListener
参数是javax.faces.event.ActionEvent
,因此不是java.awt.event.ActionEvent
,这是大多数IDE建议的第一个自动完成选项。如果你使用actionListener="#{bean.method}"
,没有争论也是错误的。如果您不想在方法中使用参数,请使用actionListener="#{bean.method()}"
。或许你真的想用action
而不是actionListener
。另见Differences between action and actionListener。PhaseListener
或任何EventListener
已更改JSF生命周期以跳过调用操作阶段,例如调用FacesContext#renderResponse()
或FacesContext#responseComplete()
。Filter
或Servlet
以某种方式阻止了对FacesServlet
的请求。rich:calendar
UI元素(或者在某些情况下,使用defaultLabel
子元素)时,RichFaces有一个“rich:placeholder
”。如果没有为日历日期设置任何值,则此错误会阻止调用bean方法。跟踪框架错误可以通过从一个简单的工作示例开始并重新构建页面直到发现错误来完成。<p:dialog>
或<p:overlayPanel>
,那么请确保他们有自己的<h:form>
。因为,这些组件默认由JavaScript重定位到HTML <body>
的末尾。因此,如果他们最初坐在<form>
内,那么他们现在不会再坐在<form>
。另见p:commandbutton action doesn't work inside p:dialog如果你仍然卡住,是时候调试了。在客户端,在webbrowser中按F12打开Web开发人员工具集。单击Console选项卡,以查看JavaScript conosle。它应该没有任何JavaScript错误。下面的屏幕截图是Chrome中的一个示例,它演示了在未声明<f:ajax>
的情况下提交启用<h:head>
的按钮的情况(如上面第7点所述)。
单击“网络”选项卡以查看HTTP流量监视器。提交表单并调查请求标题和表单数据以及响应正文是否符合预期。下面的屏幕截图是Chrome的一个示例,演示了一个简单形式的成功ajax提交,其中包含单个<h:inputText>
和一个<h:commandButton>
和<f:ajax execute="@form" render="@form">
。
(警告:当您从生产环境中发布上述HTTP请求标头的屏幕截图时,请确保在屏幕截图中对任何会话cookie进行加扰/混淆,以避免会话劫持攻击!)
在服务器端,确保服务器以调试模式启动。将调试断点放在您期望在处理表单提交期间调用的感兴趣的JSF组件的方法中。例如。在UICommand
成分的情况下,那将是UICommand#queueEvent()
,如果是UIInput
成分,那将是UIInput#validate()
。只需逐步执行代码并检查流和变量是否符合预期。下面的截图是Eclipse调试器的一个例子。
我修正了我的问题:
<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>
如果你的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请求的Push按钮。
为此,您可以分配type
属性(默认值为"submit"
)或者您可以明确使用type="submit"
。
希望这会对某人有所帮助!
我自己也遇到了这个问题,并找到了解决这个问题的另一个原因。如果您的支持bean中没有用于* .xhtml中使用的属性的setter方法,则不会调用该操作。
我最近遇到了一个问题,UICommand没有在使用IBM Extended Faces Components的JSF 1.2应用程序中调用。
我在数据表的一行(扩展版本,因此<hx:datatable>
)上有一个命令按钮,并且UICommand不会从表中的某些行触发(不会触发的行是大于默认行显示大小的行)。
我有一个下拉组件,用于选择要显示的行数。支持这一领域的价值在RequestScope
。支持表本身的数据是在某种ViewScope
(实际上,暂时在SessionScope
)。
如果行显示通过控件增加,该值也绑定到数据表的rows
属性,则由于此更改而显示的任何行都不会在单击时触发UICommand。
将此属性放在与表数据本身相同的范围内可以解决问题。
我认为在上面的BalusC#4中提到了这一点,但不仅表值需要是View或Session scoped,而且还有控制该表上显示的行数的属性。
我也有这个问题,并且在打开浏览器的Web控制台后才真正开始磨练根本原因。在此之前,我无法获得任何错误消息(即使使用<p:messages>
)。 Web控制台显示从<h:commandButton type="submit" action="#{myBean.submit}">
返回的HTTP 405状态代码。
就我而言,我有一个混合的vanilla HttpServlet通过Auth0和JSF facelets提供OAuth身份验证,并执行我的应用程序视图和业务逻辑。
一旦我重构了我的web.xml,并删除了一个中间人servlet,它就“神奇地”工作了。
最重要的是,问题是中间人servlet正在使用RequestDispatcher.forward(...)从HttpServlet环境重定向到JSF环境,而在它之前调用的servlet是用HttpServletResponse.sendRedirect重定向的(... )。
基本上,使用sendRedirect()允许JSF“容器”控制,而RequestDispatcher.forward()显然不是。
我不知道的是为什么facelet能够访问bean属性但无法设置它们,这显然是为了废除servlet和JSF的混合而尖叫,但我希望这有助于某人避免长时间的头 - 到餐桌拆裂。
调试<h:commandLink>
在richfaces
datatable
的行动拒绝解雇的问题我有很多乐趣。该表曾经在某个时刻工作,但没有明显原因停止。我不遗余力地发现,我发现我的rich:datatable
使用的是错误的rowKeyConverter
,它返回了富有乐趣的行,用作行键。这阻止了我的<h:commandLink>
行动被召唤。
还有一种可能性:如果症状是第一次调用有效,但后续调用不起作用,则可能使用PrimeFaces 3.x和JSF 2.2,详见此处:No ViewState is sent。