复合组件在绑定到视图作用域 bean 时导致唯一 ID 错误
Composite component causes unique ID error when binding to view scoped bean
我们正在将 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(根据撰写本文时的最新版本)。
提前致谢!
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
属性。
另请参阅:
- How to save state when extending UIComponentBase
我们正在将 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(根据撰写本文时的最新版本)。
提前致谢!
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
属性。
另请参阅:
- How to save state when extending UIComponentBase