2 Replies Latest reply on Oct 30, 2011 5:31 AM by Akaine Harga

    Can't find UICommand defined in a commandLink inside a dataTable

    Akaine Harga Novice

      Hello,

       

      I have a structure: a4j:form - a4j:region - dataTable - a4j:commandLink:

      <rich:column styleClass="rowMenu" style="width: #{controller_patente.esSoloLectura?'18':'60'}px;">
          <a4j:commandLink id="btn_edit" ajaxSingle="true" action="#{controller_patente.loadPatente}" oncomplete="#{rich:component('modal_patente')}.show();return false;" reRender="modal_patente" status="st_proc" rendered="#{!controller_patente.esSoloLectura}">
              <a4j:actionparam name="patenteIndex" value="#{patente.idmedpatente}" assignTo="#{controller_patente.idmedpatente}" />
              <a4j:actionparam name="editMode" value="#{true}" assignTo="#{controller_patente.editMode}" />
              <h:graphicImage value="resource:///resources/images/icon_ac_editar.png" style="border: none;" width="16" />
          </a4j:commandLink>
          <rich:toolTip for="btn_delete" value="Borrar registro" rendered="#{!controller_patente.esSoloLectura}"/>
          ...
      

       

      Then I have a PhaseListener with a method:

      public void afterPhase(PhaseEvent event){
          FacesContext facesContext = event.getFacesContext();
          UIViewRoot viewRoot = facesContext.getViewRoot();
      
          for (String clientId : facesContext.getExternalContext().getRequestParameterMap().keySet()) {
              try{
                  UIComponent component = viewRoot.findComponent(clientId);
                  System.out.println("[PhasePreInvoker] clientId="+clientId+", component="+component);
                  String me = null;
                  if (component instanceof UICommand) {
                      //System.out.println("[PhasePreInvoker] clientId="+clientId+", component="+component);
                      me = ((UICommand)component).getActionExpression().getExpressionString();
                      System.out.println("[PhasePreInvoker] methodExpression="+me);
      
                      if(me != null){
                          String mbeanAlias = me.substring(me.indexOf("#{")+2,me.indexOf("."));
                          String methodName = me.substring(me.indexOf(".")+1,me.indexOf("}"));
                          System.out.println("[PhasePreInvoker] mbeanAlias="+mbeanAlias+", methodName="+methodName);
                      }
                      break;
                  }
              }catch(Exception e){
                  //e.printStackTrace(System.out);
              }
          }
      }
      

       

      It works like a charm with any component defined outside iteration-type elements, but as soon as I put some action callers inside I get nothing. Here's an example of the output when I hit the commandLink:

      23:34:35,014 INFO  [STDOUT] [PhasePreInvoker] clientId=AJAXREQUEST, component=null
      23:34:35,014 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id31, component=org.richfaces.component.html.HtmlInputText@17d1978d
      23:34:35,014 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id34, component=org.richfaces.component.html.HtmlInputText@4134b632
      23:34:35,014 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id37comboboxField, component=null
      23:34:35,014 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id37, component=org.richfaces.component.html.HtmlComboBox@6ba5ae0f
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id40, component=org.richfaces.component.html.HtmlInputText@4a4691ff
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id43comboboxField, component=null
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:j_id43, component=org.richfaces.component.html.HtmlComboBox@5f1b2271
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id55fsp, component=javax.faces.component.UIInput@6e72597e
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id58fsp, component=javax.faces.component.UIInput@155197d8
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id61fsp, component=javax.faces.component.UIInput@1fc7f0d7
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id64fsp, component=javax.faces.component.UIInput@7f94c38d
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id67fsp, component=javax.faces.component.UIInput@7fb29f6a
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:j_id70fsp, component=javax.faces.component.UIInput@280029a5
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar, component=org.ajax4jsf.component.html.AjaxForm@22ae2427
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=autoScroll, component=null
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=javax.faces.ViewState, component=null
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=ajaxSingle, component=null
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=editMode, component=null
      23:34:35,015 INFO  [STDOUT] [PhasePreInvoker] clientId=form_buscar:dt_patentes:1:btn_edit, component=null
      23:34:35,016 INFO  [STDOUT] [PhasePreInvoker] clientId=patenteIndex, component=null
      

       

      Ok, I can see my first 7 fileds of the form, then 6 dataTable's column filters, then goes the form, then go some attributes, then the expected commandLink: form_buscar:dt_patentes:1:btn_edit. The alarming thing is that neither the commandLink nor other parameters are UICommand.

       

      So the big question is: where the heck is the ActionExpression? Since the method defined in commandLink's action is executed it has to travel to managed bean some way. Any ideas where to look for it?

       

      I'm using JSF1.2 and RF3.3.3

       

      Thanks in advance

        • 1. Re: Can't find UICommand defined in a commandLink inside a dataTable
          Christian Peter Expert

          Hmmmm never tried this approach before. You could go through the component tree  beginning with viewRoot.

           

          UIComponent root = facesContext.getViewRoot();

           

          List<UIComponent> cps = new ArrayList<UIComponent>();

           

          parseCT(root, cps);

           

          public void parseCT(UIComponent root, List<UIComponent> nodes){

          if (root != null) nodes.add(root);

           

          for (UIComponent child : root.getChildren()){

          parseCT(child, nodes);

          }

           

           

           

          You could use firebug to analyse the POST initiatet from your commandLinks. There should be all requestparameters included.

          1 of 1 people found this helpful
          • 2. Re: Can't find UICommand defined in a commandLink inside a dataTable
            Akaine Harga Novice

            I found a solution. It seems if I ignore the datatable's row index (or any other index iteration structure added, in general case) the object can be found and is not null any more. So after seeing what is returned in the request and since I've never submerged myself into the RF source code I'd say there is a class somewhere that reads the incoming parameters as text ignoring the index and goes for the object itself as it's defined in the xhtml, or at least that would be the straightest approach to hack your way through the "iteration problem".

             

            Anyways, thanks for the help