I'm building my custom JSF composite component in order to input periodicities. I've got this model:
public class Periodicity implements Serializable {
private PeriodicityType type;
private Integer value = 0;
public PeriodicityExchange() {
super();
}
/**Getter and setters**/
}
Where PeriodicityType
is an enum containing DAY
, WEEK
, MONTH
, YEAR
.
The input component for this model consists of a p:spinner
element to select a numeric value and a h:selectOneMenu
to select the periodicity type. The component works well, but now I want to have a java class backing it, so I have modified my facelet file:
<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>
And that's my java class (based in this BalusC's tutorial). It's registered as a component using the faces-config.xml file:
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;
}
}
The issue is that as soon as I use the componentType
attribute to bind my component to the java class, the component stops rendering. encodeBegin
gets called, but doing some further debugging, I've noticed that when JSF tries to get the renderer for the composite component, it returns null. The method getRenderer(FacesContext)
from the UIComponentBase
class tries to access context.getRenderKit().getRenderer(getFamily(), rendererType)
, where the family evaluates to javax.faces.Input
and rendererType
to javax.faces.Composite
.
I'm using Mojarra 2.2.12. What am I missing here?