Reputation: 1806
I have a JSF composite component util_primefaces:inplace_name that requires a "manager" backing bean that performs persistence updates when the 'name' field of an entity is edited (using p:inplace):
<cc:interface>
<cc:attribute name="manager" type="com.example.web.AbstractManager" required="false" default="#{blockManager}"/>
<cc:attribute name="element" type="com.example.entity.Element" required="true"/>
<cc:attribute name="elid" required="true"/>
<cc:attribute name="update" required="false" default="@parent"/>
..
</cc:interface>
<cc:implementation>
..
<p:inplace id="#{cc.attrs.elid}" editor="true" emptyLabel="UNDEF" >
<p:ajax
event="save"
listener="#{cc.attrs.manager.onInplaceNameSaveEvent}"
process="@this #{cc.attrs.elid}-name"
update="#{cc.attrs.update}"
/>
<h:inputText id="#{cc.attrs.elid}-name" value="#{cc.attrs.element.name}"/>
..
Where for example @ViewScoped @ManagedBean BlockManager ultimately extends an AbstractManager, which has a listener method:
public void onInplaceNameSaveEvent(AjaxBehaviorEvent ae).
[ASIDE: the reason for the unusual "elid" attribute is described here, it plays no further role in this question: Primefaces p:inplace: How to more elegantly propagate the EL expression for entity to merge ]
When I invoke the composite component passing in an explicit #{blockManager} (or other subclass of AbstractManager) it works fine:
<util_primefaces:inplace_name
element="#{tenancy}"
elid="tenancy"
manager="#{blockManager}"
/>
But if I don't pass in the #{blockManager}, on performing the inplace edit and save I get an error that the method onInplaceNameSaveEvent(AjaxBehaviorEvent) is not known:
<util_primefaces:inplace_name
element="#{tenancy}"
elid="tenancy"
/>
The error is:
WARNING: Method not found: [email protected](javax.faces.event.AjaxBehaviorEvent)
javax.el.MethodNotFoundException: Method not found: [email protected](javax.faces.event.AjaxBehaviorEvent)
at com.sun.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:155)
Q: Why is the backing bean not taken correctly using default="#{blockManager}" in the composite component attribute ?
Upvotes: 2
Views: 3712
Reputation: 23796
According to the documentation for the tag cc:attribute
, the value for default
must evaluate to a java.lang.String
.
That's why the #{blockManager}
expression is not working as you are expecting, you only can set defaults for String
attributes.
To see what happens, you can test registering the following function in a taglib (like showed here):
public static String typeOf(Object o) {
return o == null ? null : o.getClass().toString();
}
and use it in a composite component like this:
<ui:composition>
<cc:interface>
<cc:attribute name="param" type="java.lang.Integer" required="true"
default="1" />
</cc:interface>
<cc:implementation>
<h:outputText value="#{fnc:typeOf(cc.attrs.param)}" />
</cc:implementation>
</ui:composition>
Now, if you use the component without specifying param
, like this:
<my:comp />
... it will output class java.lang.String
, because it uses the result of the ValueExpression for the default attribute, which is the String "1"
.
And when you specify param:
<my:comp param="1" />
... it outputs class java.lang.Integer
, cause now it's the value resulting from coercing to the type specified for the cc:attribute
.
Upvotes: 5