如果在嵌套复合组件中使用,#{cc}在omnifaces树中解析错误

时间:2016-03-29 15:38:53

标签: jsf jsf-2.2 composite-component omnifaces

请参阅以下简化代码:

test.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:o="http://omnifaces.org/ui"
      xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
    <body>
        <h:form>
            <h1>Nested - not working</h1>
            <test:parentComp />

            <h1>Not nested - working</h1>
            <o:tree value="#{testModel.treeModel}">
                <o:treeNode>
                    <ul>
                        <o:treeNodeItem>
                            <test:childComp />
                            <o:treeInsertChildren />
                        </o:treeNodeItem>
                    </ul>
                </o:treeNode>
            </o:tree>
        </h:form>
    </body>
</html>

parentComp.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:o="http://omnifaces.org/ui"
      xmlns:cc="http://xmlns.jcp.org/jsf/composite"
      xmlns:test="http://xmlns.jcp.org/jsf/composite/test">
    <cc:interface componentType="parentComp">
    </cc:interface>

    <cc:implementation>
        <div id="#{cc.clientId}">
            <o:tree value="#{cc.treeModel}">
                <o:treeNode>
                    <ul>
                        <o:treeNodeItem>
                            <test:childComp />
                            <o:treeInsertChildren />
                        </o:treeNodeItem>
                    </ul>
                </o:treeNode>
            </o:tree>
        </div>
    </cc:implementation>
</html>

childComp.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:cc="http://xmlns.jcp.org/jsf/composite"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <cc:interface componentType="childComp">
    </cc:interface>

    <cc:implementation>
        <div id="#{cc.clientId}">
            <h:commandLink action="#{cc.childAction}" value="Click" />
        </div>
    </cc:implementation>
</html>

ParentComponent.java

@FacesComponent("parentComp")
public class ParentComponent extends UINamingContainer {

    private TreeModel treeModel;

    public ParentComponent() {
        this.treeModel = new ListTreeModel();
        this.treeModel.addChild("1").addChild("1.1");
        this.treeModel.addChild("2").addChild("2.2");
    }

    public TreeModel getTreeModel() {
        return treeModel;
    }
}

ChildComponent.java

@FacesComponent("childComp")
public class ChildComponent extends UINamingContainer {

    public void childAction() {

    }
}

TestModel.java

@RequestScoped
@Named
public class TestModel {

    private TreeModel treeModel;

    public TestModel() {
        this.treeModel = new ListTreeModel();
        this.treeModel.addChild("1").addChild("1.1");
        this.treeModel.addChild("2").addChild("2.2");
    }

    public TreeModel getTreeModel() {
        return treeModel;
    }
}

在示例中,o:tree在复合组件中使用,子组件的#{cc}被错误地解析,如果单击该链接,您将得到如下异常:

Caused by: javax.el.MethodNotFoundException: /resources/test/childComp.xhtml @10,71 action="#{cc.childAction}": Method not found: ParentComponent@422dcfd4.childAction()

如果o:树没有像第二个例子那样嵌套在复合组件中,则commandlink正在按预期工作。

这是Omnifaces的一个错误吗?我在这里做错了吗?

1 个答案:

答案 0 :(得分:1)

这确实是OmniFaces中的一个错误。我在this commit修复了它,修复程序在今天的2.3快照中可用(2.3最终预计在本周结束,所以你很准时)。

原因是,排队的操作事件基本上是caughtwrapped<o:tree>,因此它可以记住当前迭代的树节点。但是,在广播动作事件时,它将在<o:tree>本身上调用,而不是在源组件(您的命令链接)上调用。因此,只有#{cc}本身上下文中的<o:tree>被视为复合组件父级。

我通过pushing将源组件自己的复合组件父级(如果有的话)修复到EL上下文中。

Original Tree#broadcast() method

wrapped.getComponent().broadcast(wrapped);

Fixed Tree#broadcast() method

UIComponent source = wrapped.getComponent();
pushComponentToEL(context, getCompositeComponentParent(source));

try {
    source.broadcast(wrapped);
}
finally {
    popComponentFromEL(context);
}

感谢您的举报!