I want to write a more or less gemeric component, where i hand in a controller bean and the componend should display some CRUD buttons.
Following composite component:
<composite:interface>
<composite:attribute name="controller" />
<composite:attribute name="object" />
</composite:interface>
<composite:implementation>
<h:panelGrid columns="3" columnClasses="celltop">
<h:commandButton id="save" value="#{msg.saveButtonLabel}"
action="#{cc.attrs.controller.save}" />
<h:commandButton id="delete" value="#{msg.deleteButtonLabel}"
action="#{cc.attrs.controller.delete(cc.attrs.object)}" />
<h:commandButton id="cancel" value="#{msg.backButtonLabel}"
action="#{cc.attrs.controller.cancel}" immediate="true" />
</h:panelGrid>
</composite:implementation>
<viewController:buttons controller="customerController" object="#{customerController.customer}"/>
@Named
@ConversationScoped
public class CustomerController implements Serializable {
public String cancel() {
customer = null;
if (!conversation.isTransient()) {
conversation.end();
}
return "cancelled";
}
leads to the following exception when I click on the Cancel button:
javax.faces.el.MethodNotFoundException: javax.el.MethodNotFoundException: /resources/components/viewController/buttons.xhtml @25,65 action="#{cc.attrs.controller.cancel}": Method not found: customerController.cancel()
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:92)
Is it not possible to call methods on beans given to CC?
Yes you can. Your mistake is just that you passed only a plain vanilla
Stringrepresenting the managed bean name as attribute valuewhile you should actually have passed the concrete managed bean instance from the EL scope
The exception message is admittedly somewhat misleading, but it’s basically just showing the
Object#toString()of the attribute value. If it were a concrete managed bean instance, you’d rather have seen something likeor whatever is been returned by its
toString()implementation, if overridden.