绑定到视图范围的bean时,复合组件会导致唯一的ID错误

时间:2015-09-07 07:32:56

标签: jsf jsf-2 binding composite-component

我们正在迁移JSF 2.1应用程序,从JBoss AS 7.2到Wildfly以及JSF 2.2。我们遇到的问题如下:我们有一个包含在@ViewScoped bean中的复合组件。组件必须通过多个请求保留其值,因此Request Scoped bean不是解决方案。

我们获得的例外是多组件ID。在请求之后,JSF开始第二次呈现组件,并且失败。

我为此做了一个简单的演示:

MyViewBean.java

@ViewScoped
@Named
public class MyViewBean implements Serializable {

    private Component component;

    public Component getComponent() {
        return component;
    }

    public void setComponent(Component component) {
        this.component = component;
    }

    public String increment(){
        component.setCounter(component.getCounter()+1);
        return "";
    }
}

Component.java

@FacesComponent(value = "composite")
public class Component extends UINamingContainer {
    private Integer counter = 0;

    public Integer getCounter() {
        return counter;
    }

    public void setCounter(Integer counter) {
        this.counter = counter;
    }


}

compositeTest.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    template="/WEB-INF/templates/default.xhtml"
    xmlns:pelda="http://xmlns.jcp.org/jsf/composite/component">
    <ui:define name="content">
        <h1>Composite component Test!</h1>
        <h:form>
                <pelda:composite binding="#{myViewBean.component}" />
                <h:commandButton action="#{myViewBean.increment()}" value="Push me!"/>
        </h:form>

    </ui:define>
</ui:composition>

composite.xhtml

<cc:interface componentType="composite">
</cc:interface>
<cc:implementation> 
    <h:outputText id="id_hello" value="Helloka" />
    <h:outputText id="id_counter" value="#{cc.counter}" />
</cc:implementation> 
</html>

如何实现计数器可以递增(使用@RequestScoped bean重置)并且因为idUniqueness错误而失败?我们正在使用Mojarra 2.2.8(Wildfly中的默认值),也尝试使用Mojarra 2.2.12(最新编写此内容)。

提前致谢!

1 个答案:

答案 0 :(得分:2)

UIComponent个实例本身就是请求作用域。您应该永远引用请求范围之外的UIComponent个实例。请仔细阅读How does the 'binding' attribute work in JSF? When and how should it be used?以获得详尽的解释。

您只想通过继承的getStateHelper()方法将其状态保存在JSF状态中。这基本上作为视图范围。

@FacesComponent(value = "composite")
public class Component extends UINamingContainer {

    public Integer getCounter() {
        return (Integer) getStateHelper().eval("counter", 0);
    }

    public void setCounter(Integer counter) {
        getStateHelper().put("counter", counter);
    }

}

请勿忘记删除视图中的binding属性。

另见: