Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parameterized method call in <ui:include> with variable number of method parameters

I have a template that's part of a form to edit some element. The action to be performed is different depending on the page in which it is included. So I pass the action method as a parameter:

 <ui:param name="option" value="#{someOptionBean}" />
 ...
 <ui:include src="/WEB-INF/jsf/value-edit.xhtml">
    <ui:param name="controllerParam" value="#{optionController}" />
    <ui:param name="elementParam" value="#{option}" />
    <ui:param name="actionParam" value="updateOption" />
 </ui:include>

or:

 <ui:param name="property" value="#{somePropertyBean}" />
 ...
 <ui:include src="/WEB-INF/jsf/value-edit.xhtml">
    <ui:param name="controllerParam" value="#{propertyController}" />
    <ui:param name="elementParam" value="#{property}" />
    <ui:param name="actionParam" value="updateProperty" />
 </ui:include>

and in value-edit.xhtml there is a command button:

<p:commandButton value="Update" action="#{controllerParam[actionParam](elementParam)}" />

So far everything works fine.

My problem is that now the action methods don't have the same number of parameters. They are:

public void updateOption(Option option) { ... }
public void updateProperty(Item item, Prop property) { ... }

so I now want to be able to also define the action parameters to have something like:

<ui:param name="actionParam" value="updateOption(option)" />
<ui:param name="actionParam" value="updateProperty(item, property)" />

or something like:

<ui:param name="method" value="updateProperty" />
<ui:param name="parameters" value="item, property" />

I've read the docs (Value and Method Expressions / Parameterized Method Calls) and I'm not sure if this is possible.

Is there any way to achieve this?

like image 230
Tobías Avatar asked Feb 09 '15 12:02

Tobías


1 Answers

Finally I solved this creating a MethodExpression in the controller

Now the ui:include looks like:

<ui:param name="option" value="#{someOptionBean}" />
...
<ui:include src="/WEB-INF/jsf/value-edit.xhtml">
    <ui:param name="actionParam" value="#{optionController.getUpdateAction()}" />
</ui:include>

and

<ui:param name="item" value="#{someItemBean}" />
<ui:param name="property" value="#{somePropertyBean}" />
...
<ui:include src="/WEB-INF/jsf/value-edit.xhtml">
    <ui:param name="actionParam" value="#{propertyController.getUpdateAction()}" />
</ui:include>

In value-edit.xhtml the command button is:

<p:commandButton value="Update" action="#{actionParam}" />

The getUpdateAction creates the MethodExpression with the corresponding parameters for each controller:

public class OptionController {
    ...
    public void updateOption(Option option) { ... } 

    public MethodExpression getUpdateAction() {
        return createMethodExpression("#{optionController.updateOption(option)}", String.class, Option.class);
    }
    ...
}

public class PropertyController {
    ...
    public void updateProperty(Item item, Prop property) { ... }

    public MethodExpression getUpdateAction() {
        return createMethodExpression("#{propertyController.updateProperty(item, property)}", String.class, Item.class, Prop.class);
    }
    ...
}

where createMethodExpression is:

public static MethodExpression createMethodExpression(String expression, Class<?> expectedReturnType, Class<?>... expectedParameterTypes) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    return facesContext.getApplication().getExpressionFactory().createMethodExpression(
        facesContext.getELContext(), expression, expectedReturnType, expectedParameterTypes);
}
like image 80
Tobías Avatar answered Oct 19 '22 16:10

Tobías