【问题标题】:Missing parameter values in invoked method with composite components using ui:repeat使用 ui:repeat 调用具有复合组件的方法中缺少参数值
【发布时间】:2016-06-29 14:18:23
【问题描述】:

所以经过几天的调试,我们最终能够重现复合组件之间的一些奇怪交互,ui:repeatp:remoteCommand 以及我们不理解的 JSF 中的部分状态保存。

场景

复合组件使用ui:repeat 遍历对象列表。在每次迭代期间,都会包含另一个复合组件并传递参数。

<ui:composition (...)>
  <ui:repeat var="myVar" value="#{cc.attrs.controller.someList}">
    <namespace:myRemoteCommand someParam="SomeParam"/>

在包含的复合组件中,有一个自动运行的p:remoteCommand 使用组件接口中定义的参数调用方法。

<ui:component (...)>
  <p:remoteCommand actionListener="#{someBean.someMethod(cc.attrs.someParam)}"
                   autoRun="true"
                   async="true"
                   global="false">

但是,在someMethod(...) 中设置断点时,会传递一个空字符串。仅当 部分状态保存 设置为 false 时才会发生这种情况。

解决方案

我们尝试了几种解决方案,以下解决方案似乎有效(但我们不明白原因,也无法预见可能发生的任何进一步问题):

  • 我们可以将部分状态保存设置为true

  • 我们可以将复合组件模式改为ui:include

  • 我们可以删除一个或两个复合组件,并直接包含内容。

问题

为什么 JSF 会这样?复合组件ui:repeat 和参数传递之间的这种交互是什么?根据我们是否使用ui:include / 部分状态保存而改变?

我们正在使用 Primefaces 5.3、Glassfish 4.1、Mojarra 2.2.12、Java 8。

【问题讨论】:

    标签: jsf primefaces composite-component mojarra uirepeat


    【解决方案1】:

    您的代码一切正常。只是 Mojarra 的&lt;ui:repeat&gt; 坏了。您不是第一个面临与 &lt;ui:repeat&gt; 相关的状态管理问题的人。

    您的问题的根本原因是 #{cc} 目前无处可用 &lt;ui:repeat&gt; 需要访问树。实际上,&lt;ui:repeat value&gt;null。一个快速的解决方法是在UIRepeat#visitTree() 方法中显式推送#{cc}。给定 Mojarra 2.2.12,在 line 734 之前添加下面的行和 pushComponentToEL(facesContext, null)

    UIComponent compositeParent = getCompositeComponentParent(this);
    if (compositeParent != null) {
        compositeParent.pushComponentToEL(facesContext, null);
    }
    

    并在line 767 后面加上popComponentFromEL(facesContext)

    if (compositeParent != null) {
        compositeParent.popComponentFromEL(facesContext);
    }
    

    如果您不从源代码构建 Mojarra,请将 UIRepeat 的整个 source code 复制到您的项目中,保持其包结构并对其应用上述更改。 /WEB-INF/classes 中的类比/WEB-INF/lib 和服务器的/lib 中的类具有更高的类加载优先级。我至少创建了issue 4162 来解决这个问题。

    另一种方法是将 Mojarra 替换为 MyFaces,或者将 &lt;ui:repeat&gt; 替换为基于 UIData 的组件,该组件具有状态管理权限,例如 &lt;h:dataTable&gt;&lt;p:dataList&gt;

    <p:dataList type="none" var="myVar" value="#{cc.attrs.controller.someList}">
        <namespace:myRemoteCommand someParam="SomeParam" />
    </p:dataList>
    

    您可能只想应用一些 CSS 来摆脱小部件样式(边框等),但那是 trivial

    另见:

    【讨论】:

    • 非常感谢您的深入回复和分析。我们将继续启用部分状态保存。我很高兴知道这确实是 Mojarra 中的一个错误,而不是我们做错了什么。我们花了很长时间分析这个问题,直到我们意识到切换部分状态保存可以解决问题,但我们找不到这种行为的原因。
    猜你喜欢
    • 2012-11-14
    • 2016-07-26
    • 1970-01-01
    • 2013-10-19
    • 2021-07-24
    • 2016-04-16
    • 2012-08-05
    • 1970-01-01
    • 2017-04-25
    相关资源
    最近更新 更多