JSF 2:如何将包含要调用的参数的动作传递给 Facelets 子视图(使用 ui:include 和 ui:param)?

Posted

技术标签:

【中文标题】JSF 2:如何将包含要调用的参数的动作传递给 Facelets 子视图(使用 ui:include 和 ui:param)?【英文标题】:JSF 2: how to pass an action including an argument to be invoked to a Facelets sub view (using ui:include and ui:param)? 【发布时间】:2011-12-21 16:46:36 【问题描述】:

这基本上是this answer 的扩展。

我正在尝试将参数放入方法/操作调用中(用于列表/数据表中的删除按钮)。

客户:

<ui:include src="...">
  <ui:param name="acceptButtonBean" value="#repoHome" />
  <ui:param name="acceptButtonAction" value="removeIndividualDocument(#doc.id)" />
</ui:include>

子视图:

<h:commandButton value="Continue"
                 action="#acceptButtonBean[acceptButtonAction]" />
  ...
</h:commandButton>

但是,JSF 失败并出现以下异常:

...yadda, yadda
02:46:02,431 ERROR [stderr] (http--127.0.0.1-8080-5) Caused by: javax.el.MethodNotFoundException: /subviews/remove-doc-clink-popup.xhtml @37,98 action="#acceptButtonBean[acceptButtonMethod]": Method not found: com.company.project.beans.RepoHome@34b183e7.removeExternalDocument(89)()
02:46:02,431 ERROR [stderr] (http--127.0.0.1-8080-5)    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:109)
02:46:02,431 ERROR [stderr] (http--127.0.0.1-8080-5)    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
02:46:02,431 ERROR [stderr] (http--127.0.0.1-8080-5)    ... 31 more

注意

....RepoHome@34b183e7.removeExternalDocument(89)()

它不能那样工作。 JSF 似乎无论如何都会附加括号。

能否以不同的方式实现,但仍使用上述技术?如果有,怎么做?

如果没有,为什么它不起作用?指定了吗?这是 Mojarra 2.0.x 的错误吗?如果存在其他括号,我认为省略括号没有问题......

请注意,我不是在寻找替代解决方案,例如使用 f:param、f:attribute 或 f:setPropertyActionListener。

提前致谢

【问题讨论】:

对了,很好奇错误信息使用RepoHome#toString()而不是RepoHome#getClass() 【参考方案1】:

这确实不是有效的 EL。您不能在单个变量中混合方法名称和参数。这应该有效:

<ui:include src="...">
  <ui:param name="acceptButtonBean" value="#repoHome" />
  <ui:param name="acceptButtonAction" value="removeIndividualDocument" />
  <ui:param name="acceptButtonArgument" value="#doc.id" />
</ui:include>

<h:commandButton value="Continue"
    action="#acceptButtonBean[acceptButtonAction](acceptButtonArgument)" />

请注意,这与 JSF 并不完全相关,而是与 EL 相关。如果它是错误或功能,您需要阅读 EL 规范或向 EL 人员报告,而不是向 JSF 报告。 JSF 在这里无可厚非。 EL 是一个完全独立的 API,JSF 恰好使用它。


更新:事实证明,它可以在 Tomcat 7(以及可能任何其他具有 org.apache.el.* 实现的容器)上运行,但不能在 Glassfish 3(具有 com.sun.el.* 实现)上运行。显示页面失败如下:

Caused by: javax.el.ELException: Error Parsing: #p1[p2](p3)
    at com.sun.el.lang.ExpressionBuilder.createNodeInternal(ExpressionBuilder.java:174)
    at com.sun.el.lang.ExpressionBuilder.build(ExpressionBuilder.java:191)
    at com.sun.el.lang.ExpressionBuilder.createMethodExpression(ExpressionBuilder.java:242)
    at com.sun.el.ExpressionFactoryImpl.createMethodExpression(ExpressionFactoryImpl.java:81)
    at org.jboss.weld.util.el.ForwardingExpressionFactory.createMethodExpression(ForwardingExpressionFactory.java:43)
    at org.jboss.weld.el.WeldExpressionFactory.createMethodExpression(WeldExpressionFactory.java:62)
    at com.sun.faces.facelets.tag.TagAttributeImpl.getMethodExpression(TagAttributeImpl.java:222)
    ... 63 more
Caused by: com.sun.el.parser.ParseException: Encountered "(" at line 1, column 9.
Was expecting one of:
        (*snip*)

我查了EL 2.2 spec的第1.19章:

 ValueSuffix      ::= ‘.’ Identifier MethodParameters?
                    | ‘[‘ Expression ‘]’ MethodParameters?          <-- Look here
 MethodParameters ::= '(' (Expression (‘,’ Expression )* )? ')'

我非常有信心 Tomcat 是正确的。是时候向 Glassfish 男孩报告错误了:GLASSFISH-17628。


更新 2:您似乎实际上在使用 JBoss 7。我不知道它究竟使用了 Tomcat 7 的哪个分支,但我可以确认我可以使用 Tomcat 7.0 重现您的问题。 19;按下按钮后失败如下:

Caused by: javax.el.MethodNotFoundException: /test.xhtml @22,62 action="#p1[p2](p3)": Method not found: com.example.Bean@2616aa35.submit(java.lang.String)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:109)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 24 more

成功运行时我使用的是 Tomcat 7.0.22,因此它已修复在 Tomcat 7.0.20 和 7.0.22 之间的某个位置。

【讨论】:

我认为这是我的第一次尝试,不幸的是它不起作用:Caused by: javax.el.MethodNotFoundException: /subviews/remove-doc-clink-popup.xhtml @37,98 action="#acceptButtonBean[acceptButtonAction](acceptButtonArgument)": Method not found: com.company.project.beans.RepoHome@2f3e7ad6.removeIndividualDocument() BTW Eclipse 还在此处的左括号处显示警告:EL syntax error: Unexpected symbol '('. 有趣的是,Glassfish 3.1.1 (com.sun.el.*) 确实像那样混蛋,但 Tomcat 7.0.22 (org.apache.el.*) 却没有。让我看看......至于 Eclipse,我已经关闭了它的 EL 验证器,因为它是一个史诗般的失败并且一直困扰着我,所以我不能告诉任何关于这个的事情。 感谢您的帮助,现在我只需要找出 JBoss AS 7 使用的实现并报告那里的错误。您介意分享指向您的 Glassfish 错误报告的链接吗? ;-) 我做到了。但我现在意识到,这实际上并不是他完全相同的例外。让我试试旧的 Tomcat 版本...

以上是关于JSF 2:如何将包含要调用的参数的动作传递给 Facelets 子视图(使用 ui:include 和 ui:param)?的主要内容,如果未能解决你的问题,请参考以下文章

使用 jquery 调用 cakephp 动作并将数组作为参数传递

如何将参数从JSP传递给Struts 2动作

如何将模型传递给具有其他参数的动作

传递到另一个jsf页面[重复]

迁移到 tomcat 后,将枚举值作为参数从 JSF 页面传递给 bean 方法失败

JSF ui:composition 和复合组件的问题