Suppose I have a composite component
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
`enter code here` xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<composite:interface componentType="editableLabel">
<composite:attribute name="value" required="true" type="java.lang.String"/>
<composite:attribute name="oldValue" type="java.lang.String"/>
<composite:attribute name="editMode" required="false" default="#{false}" type="java.lang.Boolean"/>
<composite:attribute name="updateListener" required="false" method-signature="void actionListener()"/>
<composite:attribute name="cancelListener" required="false" method-signature="void actionListener()"/>
</composite:interface>
<composite:implementation>
<h:panelGroup id="editableLabelComponent">
<h:panelGroup rendered="#{cc.attrs.editMode}">
<p:inputText value="#{cc.attrs.value}"/>
<p:commandButton value="Update" actionListener="#{cc.update}" update="editableLabelComponent"/>
<p:commandButton value="Cancel" actionListener="#{cc.cancel}" update="editableLabelComponent"/>
</h:panelGroup>
<p:commandLink>
<p:outputLabel id="display" value="#{cc.attrs.value}" rendered="#{!cc.attrs.editMode}"/>
<p:ajax event="click" listener="#{cc.toggleEditMode}" update="editableLabelComponent"/>
</p:commandLink>
</h:panelGroup>
</composite:implementation>
</h:body>
</html>
with a FacesComponent
import org.apache.commons.lang3.StringUtils;
import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.component.FacesComponent;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import java.io.Serializable;
/**
* Created by labraham on 1/14/16.
*/
@FacesComponent(value = "editableLabel")
public class EditableLabel extends UIComponentBase implements Serializable, NamingContainer {
private static final long serialVersionUID = 108467781935083432L;
public static final String VALUE_ATTRIBUTE = "#{cc.attrs.value}";
public static final String OLD_VALUE_ATTRIBUTE = "#{cc.attrs.oldValue}";
public static final String EDIT_MODE_ATTRIBUTE = "#{cc.attrs.editMode}";
private FacesContext context;
private ELContext elContext;
@Override
public String getFamily() {
return UINamingContainer.COMPONENT_FAMILY;
}
/**
*
*/
public void update() {
ValueExpression oldValue = getAttr(OLD_VALUE_ATTRIBUTE, String.class);
String value = (String) getAttr(VALUE_ATTRIBUTE, String.class).getValue(getElContext());
oldValue.setValue(getElContext(), value);
toggleEditMode();
}
/**
*
*/
public void cancel() {
ValueExpression value = getAttr(VALUE_ATTRIBUTE, String.class);
String oldValue = (String) getAttr(OLD_VALUE_ATTRIBUTE, String.class).getValue(getElContext());
value.setValue(getElContext(), oldValue);
toggleEditMode();
}
/**
*
*/
public void toggleEditMode() {
if (StringUtils.isEmpty((String) getAttr(OLD_VALUE_ATTRIBUTE, String.class).getValue(getElContext()))) {
getAttr(OLD_VALUE_ATTRIBUTE, String.class).setValue(getElContext(),
getAttr(VALUE_ATTRIBUTE, String.class).getValue(getElContext())
);
}
ValueExpression editmode = getAttr(EDIT_MODE_ATTRIBUTE, Boolean.class);
editmode.setValue(getElContext(), !((Boolean) editmode.getValue(getElContext())));
}
/**Get value expression for a given attr.*/
private ValueExpression getAttr(final String attribute, final Class<?> attributeType) {
return getContext().getApplication().getExpressionFactory()
.createValueExpression(getElContext(), attribute, attributeType);
}
/**Get ElContext.*/
public ELContext getElContext() {
if (this.elContext == null) {
elContext = getContext().getELContext();
}
return elContext;
}
public void setElContext(final ELContext elContext) {
this.elContext = elContext;
}
/**Get faces context*/
public FacesContext getContext() {
if (this.context == null) {
context = FacesContext.getCurrentInstance();
}
return context;
}
public void setContext(final FacesContext context) {
this.context = context;
}
}
now all instances of this widget will have the baseline functionality for cancel and update as defined by the cancel() and update() functions. However in addition this basic functionality the user may want some additional functionality (for instance calling a webservice on update) which they will add by some sort of backing bean method in the updateListener and/or cancelListener attributes.
My question is Is it possible to call the method that the user attached to the listener attributes programmatically from inside the FacesComponent or am I going about this the wrong way?