JSF 无法获取自定义复合输入组件的渲染器

JSF can't get a renderer for a custom composite input component

我正在构建我的自定义 JSF 复合组件以输入周期性。我有这个型号:

public class Periodicity implements Serializable {

    private PeriodicityType type;

    private Integer value = 0;

    public PeriodicityExchange() {
        super();
    }

    /**Getter and setters**/

}

其中 PeriodicityType 是一个包含 DAYWEEKMONTHYEAR.

的枚举

该模型的输入组件由 p:spinner 元素到 select 数值和 h:selectOneMenu 到 select 周期类型组成。该组件运行良好,但现在我想要 java class 支持它,所以我修改了我的 facelet 文件:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:composite="http://xmlns.jcp.org/jsf/composite"
    xmlns:p="http://primefaces.org/ui">

<composite:interface componentType="periodicityInput">
    <composite:attribute name="value" type="model.Periodicity" />
</composite:interface>

<composite:implementation>
    <div class="col-xs-2">
        <p:spinner binding="#{cc.periodicityValue}"
            value="#{cc.attrs.value.value}" min="0" />
    </div>
    <div class="col-xs-3">
        <h:selectOneMenu binding="#{cc.periodicityType}"
            value="#{cc.attrs.value.type}" styleClass="form-control">
            <f:selectItem itemLabel="No periodicity" noSelectionOption="true" />
            <f:selectItem itemLabel="Days" itemValue="DAY" />
            <f:selectItem itemLabel="Weeks" itemValue="WEEK" />
            <f:selectItem itemLabel="Months" itemValue="MONTH" />
            <f:selectItem itemLabel="Years" itemValue="YEAR" />
        </h:selectOneMenu>
    </div>
</composite:implementation>

</html>

那是我的 java class(基于 this BalusC's tutorial)。它使用 faces-config.xml 文件注册为组件:

public class PeriodicityInput extends UIInput implements NamingContainer {

    private UIInput periodicityValue;

    private UIInput periodicityType;

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        super.encodeBegin(context);
    }

    @Override
    protected Object getConvertedValue(FacesContext context, Object newSubmittedValue)
            throws ConverterException {
        try {
            return new PeriodicityExchange(
                    Integer.parseInt(newSubmittedValue.toString().split("-")[0]),
                    newSubmittedValue.toString().split("-")[1]);
        } catch (Exception ex) {
            throw new ConverterException(ex);
        }
    }

    public String getFamily() {
        return COMPONENT_FAMILY;
    }

    public UIInput getPeriodicityType() {
        return periodicityType;
    }

    public UIInput getPeriodicityValue() {
        return periodicityValue;
    }

    @Override
    public Object getSubmittedValue() {
        return periodicityValue.getSubmittedValue() + "-" + periodicityType.getSubmittedValue();
    }

    public void setPeriodicityType(UIInput periodicityType) {
        this.periodicityType = periodicityType;
    }

    public void setPeriodicityValue(UIInput periodicityValue) {
        this.periodicityValue = periodicityValue;
    }

}

问题是,一旦我使用 componentType 属性将组件绑定到 java class,组件就会停止呈现。 encodeBegin 被调用,但做了一些进一步的调试,我注意到当 JSF 试图获取复合组件的渲染器时,它 returns 为空。 UIComponentBase class 中的方法 getRenderer(FacesContext) 尝试访问 context.getRenderKit().getRenderer(getFamily(), rendererType),其中系列的计算结果为 javax.faces.InputrendererTypejavax.faces.Composite .

我正在使用 Mojarra 2.2.12。我在这里错过了什么?

where the family evaluates to javax.faces.Input

这是不正确的。应该是javax.faces.NamingContainerUINamingContainer.COMPONENT_FAMILY.

的常数值

下面的 COMPONENT_FAMILY 可能在使用静态导入进行重构时搞砸了:

@Override
public String getFamily() {
    return COMPONENT_FAMILY;
}

上面其实是继承自UIInput而必须是UINamingContainer。最好用 FQN 指定。

@Override
public String getFamily() {
    return UINamingContainer.COMPONENT_FAMILY;
}