Properties
Components, converters and validators have properties. Usually, properties must be defined on .tld files. Also, property getter/setter and saveState/restoreState methods can be generated automatically, reducing the amount of code that should be maintained.
Properties are inherited, so if a component/converter/validator extends from a parent component/converter/validator that has some property defined, the child must have it on its .tld.
But sometimes we have the following scenarios:
- Components, converters and validators also have properties with no getter and setters (like "binding" property), which are implemented in their tag classes or facelets tag handler.
- Also, some properties implemented on a parent class are not implemented on some children, so we need to exclude it from its tld definition.
- Users can implement its own setter and getter methods for properties.
- Some properties are related only to component but should not be on tld.
- Some properties have some specific behavior (for example they could contains objects implementing StateHolder interface).
All these cases could be handled using @JSFProperty and @JSFJspProperty annotations. Below there are some examples describing how to use it.
General case
The most common case is let the property body be generated.
@JSFProperty
public abstract String getAutocomplete();
Custom Implementation of getter/setters
One example is UIViewRoot "renderKitId" property:
@JSFProperty
public String getRenderKitId()
{
//... custom implementation ...
}
public void setRenderKitId(String renderKitId)
{
//... custom implementation ...
} Properties without getter/setters
This syntax should be used only in very special cases and users should use @JSFProperty annotation/doclet instead.
@JSFComponent(type = "javax.faces.ComponentBase", family = "javax.faces.ComponentBase", desc = "base component when all components must inherit", tagClass = "javax.faces.webapp.UIComponentELTag", configExcluded = true)
@JSFJspProperty(name = "binding",
returnType = "javax.faces.component.UIComponent",
longDesc = "Identifies a backing bean property (of type UIComponent or appropriate subclass) to bind to this component instance. This value must be an EL expression.", desc = "backing bean property to bind to this component instance")
public abstract class UIComponentBase extends UIComponent
{
// .... some code ...
}Excluding properties from tld
One example is UIParameter "rendered" property:
/**
* Disable this property; although this class extends a base-class that defines a read/write rendered property, this
* particular subclass does not support setting it. Yes, this is broken OO design: direct all complaints to the JSF
* spec group.
*/
@Override
@JSFProperty(tagExcluded = true)
public void setRendered(boolean state)
{
super.setRendered(state);
// call parent method due TCK problems
// throw new UnsupportedOperationException();
}Properties with different name in component and tag class
One example is UICommand "action" property. To change it on tld, use "jspName".
@JSFProperty(stateHolder = true, returnSignature = "java.lang.Object", jspName = "action")
public MethodExpression getActionExpression()
{
// .... some code ...
}MethodExpression/MethodBinding properties
@JSFProperty(stateHolder = true, returnSignature = "void", methodSignature = "javax.faces.event.ActionEvent")
public MethodBinding getActionListener()
{
// .... some code ...
}
@JSFProperty(stateHolder = true, returnSignature = "java.lang.Object", jspName = "action")
public MethodExpression getActionExpression()
{
// .... some code ...
}