4

考虑一个带有输入文本和一些验证的简单页面。该页面作为视图状态包含在 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 上运行

4

0 回答 0