在JSF 2复合组件中使用id-attribute和目标

时间:2013-11-18 16:52:57

标签: jsf jsf-2 el composite-component ajax4jsf

我正在尝试为按钮创建一个JSF 2.1复合组件:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jstl/core">

    <composite:interface>
        <composite:attribute name="id" required="true" type="java.lang.String" />
        <composite:attribute name="label" required="true" type="java.lang.String" />
        <composite:attribute name="action" method-signature="java.lang.String action()" targets="#{cc.attrs.id}" />
    </composite:interface>

    <composite:implementation>
        <a4j:commandLink id="#{cc.attrs.id}">
            <span style="linkButton"><h:outputText value="#{cc.attrs.label}" /></span>
        </a4j:commandLink>
    </composite:implementation>
</html>

我对此代码的问题是,在呈现页面时它会出现以下异常:

java.lang.ClassCastException: javax.faces.component.UINamingContainer cannot be cast to javax.faces.component.ActionSource2
at com.sun.faces.application.view.FaceletViewHandlingStrategy$MethodRetargetHandlerManager$ActionRegargetHandler.retarget(FaceletViewHandlingStrategy.java:1536)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.retargetMethodExpressions(FaceletViewHandlingStrategy.java:689)
at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.applyNextHandler(CompositeComponentTagHandler.java:201)
at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:53)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:196)
...

当我使用#{cc.attrs.id}之类的定义字符串替换idtargets属性中的myId时,该组件按预期工作但这使得它不能在同一个字段中重复使用页面,因此首先消除了创建复合组件的感觉。

我在这里错过了什么吗?

1 个答案:

答案 0 :(得分:11)

在JSF组件树中,#{cc.attrs.id}已经使用<cc:implementation>。您不应该在另一个组件上重用任何使用过的组件ID。您的具体功能要求不清楚,投诉“不能在同一页面重复使用”真的没有意义,因为它完全正常(你实际上尝试过它并调查生成的HTML输出?),所以它是很难理解你所面临的问题。也许您完全忽略了复合组件隐式继承自NamingContainer并且已经将自己的id添加到子项的ID中,如<h:form><h:dataTable>等也可以吗?

如果您的唯一要求是能够像<f:ajax render="compositeId" />那样通过ajax从外部引用复合组件,那么您需要将<cc:implementation>的正文包裹在普通的HTML <span>中或<div>如下#{cc.clientId}代替:

<div id="#{cc.clientId}">

另见: