f:setPropertyActionListener inside ui:repeat 和 accordion 的奇怪行为

Strange bevavior of f:setPropertyActionListener inside ui:repeat and accordion

在一个 jsf/primefaces(版本 6.2)项目中,我有这段代码可以在手风琴中显示记录列表。 所有记录都正确显示。
ui:repeat 中,我有一个 p:commandButton 可以使用 f:setPropertyActionListener 保存一些文本片段 (fragmt)。

我还实现了第二个 f:setPropertyActionListener 来获取对象 (sRes)。这个工作正常。
但是 currentFrag 变量总是填充了最后一个手风琴的文本片段。

<h:form id="accord" >
<p:accordionPanel value="#{myBean.lucSearchResults}" var="sRes" multiple="true">
<p:tab title="#{sRes.score}"> 

    <ui:repeat value="#{sRes.frags}" var="fragmt">
    <h:panelGrid columns="2" cellpadding="10">
        <h:panelGrid columns="1" cellpadding="10">
        <h:outputText value="#{fragmt}" escape="false"/>
        <hr/>
        </h:panelGrid>

        <h:panelGrid columns="1" cellpadding="10">
        <p:commandButton action="#{myBean.saveFrag}" value="Save" >
            <f:setPropertyActionListener value="#{sRes}" target="#{myBean.currentSearchResult}" />
            <f:setPropertyActionListener value="#{fragmt}" target="#{myBean.currentFrag}" />
        </p:commandButton>
        </h:panelGrid>
    </h:panelGrid>
    </ui:repeat>
</p:tab>
</p:accordionPanel>
</h:form>

我在 JSF 和 Java 方面有着长期的经验。对于这种奇怪的行为,我没有任何解释。
非常感谢有关此问题的任何帮助或指示。

我可以使用 Primefaces 7.0、Mojarra 2.3.3、JVM 1.8 重现此内容。0_152-b16、Apache Tomcat 9.0.21、Openwebbeans 2.0.7 使用此示例:

<h:form id="frm">
    <p:accordionPanel id="accordion" value="#{myBean.cats}" var="cat"
        multiple="true">
        <p:tab id="tab" title="#{cat.name}">
            <ui:repeat var="kid" value="#{cat.kitten}">
                <h:panelGroup id="group">
                    <p:commandButton id="cmdSubmit" action="#{myBean.doSomething()}"
                        value="submit #{cat.name} - #{kid.name} " process="@form"
                        update=":frm:output">
                        <f:setPropertyActionListener value="#{cat}"
                            target="#{myBean.cat}" />
                        <f:setPropertyActionListener value="#{kid}"
                            target="#{myBean.kid}" />
                    </p:commandButton>
                </h:panelGroup>
            </ui:repeat>
        </p:tab>
    </p:accordionPanel>

    <h:outputText id="output"
        value="#{myBean.cat.name} - #{myBean.kid.name}" />
</h:form>

这是我的豆子:

package my.package;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 43L;

    private List<Cat> cats;

    private Cat cat;

    private Cat kid;

    @PostConstruct
    public void init() {
        cats = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            final Cat cat = new Cat();
            cats.add(cat);
            cat.setName(String.valueOf(i));
            cat.setKitten(new ArrayList<>());
            for (int j = 0; j < 5; j++) {
                final Cat kid = new Cat();
                kid.setName(i + "." + j);
                cat.getKitten().add(kid);
            }
        }
    }


    public void doSomething() {
        System.err.println(cat.getName() + " / " + kid.getName());
    }

    // getters & setters ...

    public static class Cat {
        private String name;
        private List<Cat> kitten;

        // getters & setters ...
    }
}

当击中例如命令按钮显示为“5 - 5.4”,输出为“5 - 9.4”:


将 p:accordion/p:tab 替换为 ui:repeat 时,此示例按预期工作。这表明它与 primefaces 动态选项卡有关 并且可能值得提交错误报告

当用 process="@this"process="group" 替换 process="@form" 时,它也按预期工作并输出按下按钮的正确标签。


更好的解决方法 是在 tabView/accordion/dataTable 和不同的 ui:repeat 实现之间使用 p:repeat component implemented to solve known incompatibilities