考虑一个带有输入文本和一些验证的简单页面。该页面作为视图状态包含在 Spring webflow 中。在验证失败时,需要重新显示相同的视图状态,包括验证消息。这工作正常。使用封装输入和消息的复合组件也可以正常工作。
但是,在另一个复合材料中使用相同的复合组件会导致以下错误:
FacesException: Cannot add the same component twice
此异常源于一个名为handleAddRemoveWithAutoPrune的方法,该方法将组件添加到动态操作列表中,如果应该再次添加组件,则会引发错误。
这是重现该行为的示例:
JSF 页面
<h:form id="form">
<h:inputText id="text" value="#{bean.someValue}" >
<f:validateLength maximum="3" />
</h:inputText>
<h:message for="text" />
<!-- This will work -->
<test:ccInner anything="Blubb" />
<!-- This will not work -->
<test:ccOuter id="outer" title="Outer Component">
<test:ccInner id="inner" anything="Inner Component" />
</test:ccOuter>
<h:commandButton id="button" type="submit" value="Submit"
action="#{bean.doStuff}" />
</h:form>
成分
内
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="anything" />
</cc:interface>
<cc:implementation>
#{cc.attrs.anything}
</cc:implementation>
</html>
外
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="title" />
</cc:interface>
<cc:implementation>
#{cc.attrs.title}
<cc:insertChildren />
</cc:implementation>
</html>
(省略 bean 和流定义。普通标准的东西)
我研究了一段时间。其他有类似问题的人通常在迭代组件(例如dataTable)中使用组合时遇到它,因此组件将在视图创建和视图恢复时动态添加。然后在回发到同一视图时会出现问题,例如,请参见此处的这张票。在那里,错误是由原始海报的编码方法中的缺陷引起的,但是,我的组件简单明了,后面没有自定义 Java,所以这对我没有帮助......
尽管如此,我还是找到了两种解决方法: 如Spring Webflows 文档中所述,当发生到相同视图状态的转换时,Webflow 会自动执行重定向。
1)当通过添加关闭此行为时
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-attributes>
<webflow:redirect-in-same-state value="false"/>
</webflow:flow-execution-attributes>
</webflow:flow-executor>
到webflow.xml
问题消失了。但是,正如文本所建议的那样,原始重定向是理想的行为,以防止在某些浏览器(例如 chrome)中按 F5 或使用后退/前进时出现双重表单提交和通知。
2)如文所述,Ajax请求不会引起重定向,所以添加<f:ajax execute="@form" render="@form" />
提交按钮也能解决问题。但是我真的想使用 Ajax 来提交完整的表单吗?这对我来说似乎有点荒谬。
虽然这暂时有效,但 1) 有严重的缺点,并且 2) 使事情变得更复杂一些,也可能并不总是可取的。因此,我宁愿解决原始问题(或者首先理解它)。此外,如果这是底层实现中的问题,最好提交一份错误报告(如果还没有的话)。
编辑:使用 Mojarra 2.1.21、JSF 2.1、Spring Webflow 2.3.2 在 JBoss 上运行