JSF custom component: support for user type arguments, setter attribute is never called

I created my custom JSF component according to one of many tutorials (I use PrimeFaces ), I added an argument that the component was passed successfully.

<c:custom command="command"/> 
 public void setCommand(String command) { log.debug("setCommand {}", command); this.command = command; } 

But I need a custom type argument, and this is something that I could not find in textbooks that handle only the most trivial cases.

 <c:custom image="#{currentImageBean.image}"/> 
 public void setImage(Object image) { log.debug("setImage {}", image); this.image = (Image) image; } 

bean returns an object of type Image , but the setter is not called. I expected this to work, because otherwise a good tutorial should mention this case, but now I’m stuck in the worst of errors: nothing happens and the magazines say nothing about why ... So, what not so what do I need to change, where to look for a potential error?

+6
source share
1 answer

This has nothing to do with custom types. This is due to the use of literal (static) values ​​compared to EL, as in attributename="attributevalue" compared to attributename="#{attribute.value}" .

This behavior is also expected by specification. Attribute values ​​that are EL expressions ( ValueExpression s) are set by UIComponent#setValueExpression() . They should only be evaluated when they are actually requested, usually while viewing a visualization. They should not be evaluated directly during the baking of an instance of UIComponent , as this may violate the nature of dynamic expressions (think about the dependence on the current iteration cycle of the data table).

It is better to delegate attribute receivers / setters that may contain an EL value expression for UIComponent#getStateHelper() instead of local properties. setValueExpression() will end up in the StateHelper as StateHelper . UIComponent#getAttributes() also resolves values ​​from StateHelper .

 public Image getImage() { return (Image) getStateHelper().eval("image"); } public void setImage(Image image) { getStateHelper().put("image", image); } 

Note that there is no local property. Therefore, when you need an (estimated) attribute value, just call the recipient.

To achieve your initial functional requirement, which is the registration of the set attribute, you can add the registration operator to the setValueExpression() override, which is delegated to super .

 @Override public void setValueExpression(String name, ValueExpression binding) { log.debug(....); super.setValueExpression(name, binding); } 
+6
source

All Articles