未能为复合组件设置默认值
Failing to set a default value to the composite component
我有一个 List<String>
并且我在数据表中成功地表示了它;现在我正在尝试用它创建一个复合组件,但似乎我一直无法理解 StateHelper
是如何工作的。
我想做的是,如果 xhtml 传递的 value
属性的计算结果为 null
,则自动创建一个新的 List<String>
。现在,唯一可能的操作是单击向列表添加新项目的按钮。
我的组件
<cc:interface componentType="testComponent">
<cc:attribute name="value" required="true" type="java.util.List"/>
</cc:interface>
<cc:implementation>
<f:event type="postAddToView" listener="#{cc.init}" />
<p:dataTable id="data" value="#{cc.data}" var="_data">
<p:column headerText="Nombre / Relación">
<h:outputText value="#{_data}" />
</p:column>
</p:dataTable>
<p:commandButton value="Añadir" process="@this" update="data"
actionListener="#{cc.addData}" ajax="true"/>
</cc:implementation>
组件bean是
@FacesComponent("testComponent")
public class TestComponent extends UIOutput implements NamingContainer {
private static final String LISTA_DATOS = "LST_DATOS";
private static final Logger log = Logger.getLogger(TestComponent.class.getName());
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public List<String> getData() {
@SuppressWarnings("unchecked")
List<String> data = (List<String>) this.getStateHelper().get(LISTA_DATOS);
return data;
}
public void setData(List<String> data) {
this.getStateHelper().put(LISTA_DATOS, data);
}
public void addData() {
List<String> data = (List<String>)this.getData();
data.add("HOLA");
this.setData(data);
}
public void init() {
log.info("En init()");
if (this.getStateHelper().get(LISTA_DATOS) == null) {
if (this.getValue() == null) {
this.getStateHelper().put(LISTA_DATOS, new ArrayList<String>());
} else {
this.getStateHelper().put(LISTA_DATOS, this.getValue());
}
}
}
组件就是这样调用的
<h:form>
<imas:editorTest value="#{testBean.data1}"/>
</h:form>
<h:form>
<imas:editorTest value="#{testBean.data2}"/>
</h:form>
其中 testBean
为:
private List<String> data1 = new ArrayList<>(Arrays.asList("ONE", "TWO", "SIXTYNINE"));
private List<String> data2 = null;
public List<String> getData1() {
return this.data1;
}
public void setData1(List<String> data1) {
this.data1 = data1;
}
public List<String> getData2() {
return this.data2;
}
public void setData2(List<String> data2) {
this.data2 = data2;
}
我发现的问题是,当传递 data2
(null
列表)时,单击按钮会添加一个新项目,但只有前两次;在那之后,无论我点击按钮多少次,都没有新项目添加到列表中(日志中没有显示异常)。相反,向使用 data1
.
初始化的组件添加任意数量的项目是没有问题的
我观察到的一件事让我认为我在滥用 getStateHelper
是,当我单击按钮时,init()
方法被执行两次,在那个时候,this.getStateHelper().get(LISTA_DATOS)
是 null
,而我预计它不为空,因为在首次呈现组件时已将其初始化。我希望 getStateHelper
在调用之间携带这样的状态,我哪里错了?
哦!我在 JDK 7.
中使用 Wildfly 8.1(未升级)
深入挖掘,我发现了一些 bug 的证据,所以 I reported it。我会更新答案,看看它是否真的是一个错误或我的一些重大误解。
我有一个 List<String>
并且我在数据表中成功地表示了它;现在我正在尝试用它创建一个复合组件,但似乎我一直无法理解 StateHelper
是如何工作的。
我想做的是,如果 xhtml 传递的 value
属性的计算结果为 null
,则自动创建一个新的 List<String>
。现在,唯一可能的操作是单击向列表添加新项目的按钮。
我的组件
<cc:interface componentType="testComponent">
<cc:attribute name="value" required="true" type="java.util.List"/>
</cc:interface>
<cc:implementation>
<f:event type="postAddToView" listener="#{cc.init}" />
<p:dataTable id="data" value="#{cc.data}" var="_data">
<p:column headerText="Nombre / Relación">
<h:outputText value="#{_data}" />
</p:column>
</p:dataTable>
<p:commandButton value="Añadir" process="@this" update="data"
actionListener="#{cc.addData}" ajax="true"/>
</cc:implementation>
组件bean是
@FacesComponent("testComponent")
public class TestComponent extends UIOutput implements NamingContainer {
private static final String LISTA_DATOS = "LST_DATOS";
private static final Logger log = Logger.getLogger(TestComponent.class.getName());
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
public List<String> getData() {
@SuppressWarnings("unchecked")
List<String> data = (List<String>) this.getStateHelper().get(LISTA_DATOS);
return data;
}
public void setData(List<String> data) {
this.getStateHelper().put(LISTA_DATOS, data);
}
public void addData() {
List<String> data = (List<String>)this.getData();
data.add("HOLA");
this.setData(data);
}
public void init() {
log.info("En init()");
if (this.getStateHelper().get(LISTA_DATOS) == null) {
if (this.getValue() == null) {
this.getStateHelper().put(LISTA_DATOS, new ArrayList<String>());
} else {
this.getStateHelper().put(LISTA_DATOS, this.getValue());
}
}
}
组件就是这样调用的
<h:form>
<imas:editorTest value="#{testBean.data1}"/>
</h:form>
<h:form>
<imas:editorTest value="#{testBean.data2}"/>
</h:form>
其中 testBean
为:
private List<String> data1 = new ArrayList<>(Arrays.asList("ONE", "TWO", "SIXTYNINE"));
private List<String> data2 = null;
public List<String> getData1() {
return this.data1;
}
public void setData1(List<String> data1) {
this.data1 = data1;
}
public List<String> getData2() {
return this.data2;
}
public void setData2(List<String> data2) {
this.data2 = data2;
}
我发现的问题是,当传递 data2
(null
列表)时,单击按钮会添加一个新项目,但只有前两次;在那之后,无论我点击按钮多少次,都没有新项目添加到列表中(日志中没有显示异常)。相反,向使用 data1
.
我观察到的一件事让我认为我在滥用 getStateHelper
是,当我单击按钮时,init()
方法被执行两次,在那个时候,this.getStateHelper().get(LISTA_DATOS)
是 null
,而我预计它不为空,因为在首次呈现组件时已将其初始化。我希望 getStateHelper
在调用之间携带这样的状态,我哪里错了?
哦!我在 JDK 7.
中使用 Wildfly 8.1(未升级)深入挖掘,我发现了一些 bug 的证据,所以 I reported it。我会更新答案,看看它是否真的是一个错误或我的一些重大误解。