I’ve created my custom JSF component according to one of many tutorials (I’m using PrimeFaces), I’ve added an argument which was successfully passed to component.
<c:custom command="command"/>
public void setCommand(String command) {
log.debug("setCommand {}", command);
this.command = command;
}
But I need the argument of custom type, and that’s something that I couldn’t find in tutorials, which are handling only the most trivial cases.
<c:custom image="#{currentImageBean.image}"/>
public void setImage(Object image) {
log.debug("setImage {}", image);
this.image = (Image) image;
}
The bean is returning the object of type Image, but the setter is not called. I’ve expected that this will work, because otherwise a good tutorial should mention that case, but now I’m stuck with the worse of the errors: nothing happens, and there’s nothing in logs suggesting why… So, what is wrong, what I need to change, where to look for potential error?
This has nothing to do with custom types. This has to do with using literal (static) values versus EL as in
attributename="attributevalue"versusattributename="#{attribute.value}".This behavior is expected and by specification. Attribute values which are EL expressions (
ValueExpressions) are been set byUIComponent#setValueExpression(). They are namely supposed to be evaluated only when they are really been requested, usually during view render time. They shouldn’t be evaluated directly during baking theUIComponentinstance as that would defeat the nature of dynamic value expressions (think of depending on the current iteration round of data table).Better is to delegate the getters/setters of attributes which can hold an EL value expression to
UIComponent#getStateHelper()instead of to local properties. ThesetValueExpression()will namely ultimately also end up in theStateHelper. TheUIComponent#getAttributes()also resolves the values from theStateHelper.Note that there’s no local property. So when you need the (evaluated) value of the attribute, then just call the getter.
In order to achieve your initial functional requirement, which is the logging of the set attribute, you might want to add the logging statement to the
setValueExpression()override which delegates tosuper.