Albert Setiadi
Albert Setiadi

Reputation: 11

Can not assign variable from another Beans with composite component in MyFaces

Version : MyFaces 2.2.8

Issues : I have some composite component that will assign some value for the variable which passed from the composite. It works well in Mojara 2.2.12 (before im migrating to Myfaces 2.2.8).

This is my composite code : info.xhtml

<composite:interface>
    <composite:attribute name="id" />
    <composite:attribute name="methodToGetRecordFromInfo" method-signature="java.util.List action(id.co.sg.core.Dto)" required="true" />
    </composite:interface>

<p:dataTable id="tblInfoCodeComponent"
  var="codeComponent"
  value="#{infoBean.grid}"

    <p:columnGroup type="header">
        <p:row>
            <p:column headerText="CodeComponent"/>
        </p:row>
    </p:columnGroup>

    <p:column>
          <p:commandLink value="#{codeComponent.map['componentCode']}"
                  process="@this"
                  icon="ui-icon-search"
                  update="#{infoBean.field.map['update']}">
          <f:setPropertyActionListener
            value="#{infoBean.wrap(codeComponent)}"
            target="#{cc.attrs.methodToGetRecordFromInfo}" />
          </p:commandLink>
    </p:column>

</p:dataTable>

and this is the method in composite bean code infoBean.java

public Dto wrap(Dto codeComponentRecord) {
    Dto result = new Dto();

    result.putString("callerId", "callerId");
    result.putDto("record", codeComponentRecord.clone());

    return result;
}

Dto, was some kind of map object that we use to simplify for our works.

and this is how we use it in the main xhtml

input.xhtml

<info:codeComponentInfo id="codeComponentInfo" methodToGetRecordFromInfo="#{inputBean.selectedInfoRecord}" />   

and this is the code in inputBean.java

private Dto selectedInfoRecord;

public void setSelectedInfoRecord(Dto infoDto){

    String id = infoDto.getString("callerId","");
        activeRow.putDto("codeComponent", infoDto.getDto("record"));            

}

public Dto getSelectedInfoRecord() {
    return selectedInfoRecord;
}

when im use MyFaces 2.2.8, the setSelectedInfoRecord method does not invoke. so, i can't get the result i pick from the infoBean in the inputBean.

and then i saw this article Pass Argument to a composite-component action attribute

so i modified that actual info.xhtml code into this one

<composite:interface>
   <composite:attribute name ="beanName" type="java.lang.Object"/>
   <composite:attribute name ="methodName" type="java.lang.String"/>
</composite:interface>

...

<f:setPropertyActionListener
  value="#{infoBean.wrap(codeComponent)}"
  target="#{cc.attrs.beanName[cc.attrs.methodName]}" />

and this is the new input.xhtml

<info:goodsCodeComponentInfo id="goodsCodeComponentInfo"  beanName="infoBean" methodName="selectedInfoRecord"/> 

but this is what i found

ERROR BusinessExceptionHandler - $$$$$ An unhandled exception occured org.apache.myfaces.view.facelets.el.ContextAwarePropertyNotFoundException: javax.el.PropertyNotFoundException: Property 'selectedInfoRecord' not found on type java.lang.String

and then i try to modify the info.xhtml into this one

 <f:setPropertyActionListener
      value="#{infoBean.wrap(codeComponent)}"
      target="#{cc.attrs.beanName.methodName}" />

or this one

<f:setPropertyActionListener
    value="#{infoBean.wrap(codeComponent)}"
    target="#{cc.attrs.beanName.selectedInfoRecord}" />

and still have the same error as above..

so i try to mod it once again into this one

<f:setPropertyActionListener
    value="#{infoBean.wrap(codeComponent)}"
    target="#{inputBean.selectedInfoRecord}" />

It works well !!! but this is not what i need, i need to passing the bean name from the parameters.

anyone can help me to solve this case?

i'm using Java 8 and tomcat 8.0.30 and EL 3

Upvotes: 0

Views: 594

Answers (1)

lu4242
lu4242

Reputation: 2318

I have checked the problem looking for a possible bug, but there is no bug. Instead, it is something related to understand how f:setPropertyActionListener works.

This tag set the value retrieved from the EL expression into the property pointed by the "target" attribute. If you try to call a method using "target" attribute it will not work, because that is not how it was designed.

The right way to do it is in this way:

<info:codeComponentInfo bean="#{inputBean}" methodName="selectedInfoRecord"/>

And in the composite component:

<cc:attribute name ="bean" type="java.lang.Object"/>
<cc:attribute name ="methodName" type="java.lang.String"/>
....
<f:setPropertyActionListener
                value="#{infoBean.wrap(codeComponent)}"
                target="#{cc.attrs.bean[cc.attrs.methodName]}" />

The key thing here is you need to pass a reference to the bean, and in that way the chain will be correctly solved.

Upvotes: 2

Related Questions