1

I implemented with success the converter for h:selectOneMenu used by one bean but I want to use the same converter from a different bean instead to create the same converter another time.

currently I have:

Converter

@FacesConverter(value = "csiConverter")
public class CsiConverter implements Converter {

@Override
public Object getAsObject(FacesContext ctx, UIComponent uiComponent, String dcId) {
    ValueExpression vex =
            ctx.getApplication().getExpressionFactory()
                    .createValueExpression(ctx.getELContext(),
                            "#{cfgbean}", CfgDbBean.class);

   ...
}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
    return ((Csi) o).getCsi();
}

and the xhtml

     <div class="form-group">
      <label>CSI</label>
     <h:selectOneMenu id="csi" styleClass="form-control" value="#{cfgbean.csi}" converter="csiConverter">
            <f:selectItems var="csival" itemLabel="#{csival.csi} - #{csival.name}" itemValue="${csival}" value="#{cfgbean.csilist}" />
        </h:selectOneMenu>          
      </div>

this is working all fine. Now I would like to create in a different xhtml the same selectOneMenu contacting a different bean for the same purpose to show the same content.

Problem is that inside the Converter class is cabled the bean reference and bean class.(createValueExpression(ctx.getELContext(), "#{cfgbean}", CfgDbBean.class);)

How can avoid to cable that references and have a generic csiConverter for all Beans?

thanks

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Matt Vegas
  • 453
  • 5
  • 17
  • 1
    Possible duplicate of [Custom converter in JSF 2 with arguments](https://stackoverflow.com/questions/11613134/custom-converter-in-jsf-2-with-arguments) – Jasper de Vries Dec 06 '17 at 11:44
  • thanks for reply, I will try to create a dedicated bean and refer to it from all others, I guess should be more easy then implementing what read about. I will share and comment later. – Matt Vegas Dec 06 '17 at 14:39
  • i tried but it's not working. so we need to add some check into the getasobject method to get the object from a different bean – Matt Vegas Dec 07 '17 at 11:03

2 Answers2

0

I have a converter where the getAsObject method optionally uses an attribute to pass the bean name. If the attribute is not set I use the component's value attribute to detect the type of object the value is bound to:

ValueExpression valueExpression = uiComponent.getValueExpression("value");
Class<?> type = valueExpression.getType(ctx.getELContext());

From the type I can determine the bean name. This might be an option for you as well.

In my case:

String beanName = type.getSimpleName() + "Bean";
beanName = beanName.substring(0, 1).toLowerCase() +
           beanName.substring(1);

If you are using the same type on different beans, you should be able to get the bean name from:

valueExpression.getExpressionString()

It returns the original string used to create the expression, unmodified. In your case:

#{cfgbean.csi}

Simply remove the .csi part from that string to get the bean. If your beans extends an abstract bean / implements an interface like CsiHolder (or whatever name you gave it), you can can get the bean like:

ctx.getApplication().evaluateExpressionGet(ctx, "#{cfgbean}", CsiHolder.class)
Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
  • can you please share more infos regarding how to implement that? thanks – Matt Vegas Dec 07 '17 at 11:04
  • .. but I guess you are using the same type in different beans, right? – Jasper de Vries Dec 07 '17 at 11:23
  • yes different bean is using the same time. doing as proposed i get FormAdd.xhtml @162,154 value="#{formbean.csi}" so i should parse this value string in order to get the bean name and after mapping the java class, is it right? – Matt Vegas Dec 07 '17 at 11:30
  • In that case you can use `valueExpression.getExpressionString()` – Jasper de Vries Dec 07 '17 at 11:43
  • yes this return the correct #{cfgbean.csi}, what about getting the class of the bean? because this Class> type = valueExpression.getType(ctx.getELContext()); return the Csi object – Matt Vegas Dec 07 '17 at 12:03
  • seems fine ... Object p = ctx.getApplication().evaluateExpressionGet(ctx, "#{cfgbean}", Object.class); if(p instanceof CfgBean){ i need more time, i will test with all others. thanks for the help! :) – Matt Vegas Dec 07 '17 at 13:10
0

This is the part done with the help of Jasper.

    ValueExpression valueExpression = uiComponent.getValueExpression("value");
    String beanName = valueExpression.getExpressionString();
    //#{formbean.data}
    if(beanName.contains("#{")){
        String[] output = beanName.split("\\{");
        if(output.length!=2){
            throw new IllegalArgumentException(beanName + " - invalid format!");
        }else{
            if(output[1].contains(".")){
                String[] bean = output[1].split("\\.");
                beanName = bean[0];
            }else{
                throw new IllegalArgumentException(output[1] + " - invalid format!");
            }
        }
    }else{
        throw new IllegalArgumentException(beanName + " - invalid format!");
    }

    Object p = ctx.getApplication().evaluateExpressionGet(ctx, "#{"+beanName+"}", Object.class);

    if(p instanceof FormBean){
        FormBean p2 = (FormBean) p;
        return p2.getName(dcId); 
    }
    ...
    ...
    ...

It's working fine and I fixed the issue.

Matt Vegas
  • 453
  • 5
  • 17