4 Replies Latest reply on Nov 2, 2009 7:04 PM by Jose Antonio Da Rocha Padilla

    a4j:commandLink calling all actions in xhtml!!

    Miguel Cohnen Newbie

      Hi,


      obviously there's something I'm missing with richfaces a4j... This is the simple example I have made.


      Here the xhtml




      <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <ui:composition xmlns="http://www.w3.org/1999/xhtml"
          xmlns:s="http://jboss.com/products/seam/taglib"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:rich="http://richfaces.org/rich"
          xmlns:a="http://richfaces.org/a4j" 
          template="layout/template.xhtml">
      
      <ui:define name="body">
           <ul>
                <ui:repeat var="_i" value="#{test.strings}">
                     <li>#{_i}</li>
                </ui:repeat>
              </ul>
              <s:div id="date">
                   #{test.date}
              </s:div>
              <h:form>
                   <a:commandLink value="Go" action="#{test.nothing}" reRender="date"/>
              </h:form>
       </ui:define>
      </ui:composition>



      Here the Test Component



      package es.cohnen.pistayhora.session;
      
      import java.util.ArrayList;
      import java.util.Date;
      import java.util.List;
      
      import org.jboss.seam.annotations.Name;
      
      @Name("test")
      public class Test {
           private Date date = new Date();
      
           public void nothing(){
                System.out.println("Doing nothing...");
                date = new Date();
           }
           
           public List<String> getStrings(){
                System.out.println("Loading strings...");
                List<String> res = new ArrayList<String>();
                for (int i=0; i<20; i++){
                     res.add(""+i);
                }
                return res;
           }
           
           public Date getDate() {
                return date;
           }
      
           public void setDate(Date date) {
                this.date = date;
           }
      }
      



      What I want: I want to print the ul in the site, and then, when I click the a4j link, I want the 'nothing' method to be called, but without calling the 'getStrings' method (Or whatever another method was called in the xhtml file.


      The traces I get are:


      19:28:31,379 INFO  [STDOUT] Loading strings... (First call, loading page)
      19:28:36,145 INFO  [STDOUT] Loading strings... (ajax call)
      19:28:36,161 INFO  [STDOUT] Doing nothing... (ajax call)
      



      Why is the 'getStrings' method called when I click my a4j link? I have tried using bypassupdates, singleAjax, immediate... none of them did the job...


      Thank you in advance! I hope it is clear enough!







        • 1. Re: a4j:commandLink calling all actions in xhtml!!
          Nikos Paraskevopoulos Novice

          Hi,


          This has nothing to do with Seam or RichFaces. It is how JSF works. You see, the <ui:repeat> will create some components during view creation by iterating over the List<String> returned by getStrings(). When processing your submission, JSF has to iterate again over the same list, so that any components created will process their inputs from the request. So, getStrings() is called (at least) once again.


          The getters are called (possibly) many times during a JSF processing cycle, therefore getters should be caching, e.g:


               private List<String> strings;
          
               public List<String> getStrings(){
                    if( strings == null ) {
                         System.out.println("Loading strings...");
                         strings = new ArrayList<String>();
                         for (int i=0; i<20; i++){
                              strings.add(""+i);
                         }
                    }
                    return strings;
               }
          

          • 2. Re: a4j:commandLink calling all actions in xhtml!!
            Dmitry Shultz Newbie

            Looks like the view tree is processed anyway (even if you specify component in reRender) and new test is created or may be the tree is processed again because the old test doesn't exist anymore (Event scope)


            Try to use the a4j:region to limit the part of the tree processed on the server or change the component scope.

            • 3. Re: a4j:commandLink calling all actions in xhtml!!
              Miguel Cohnen Newbie

              Thank you for your answers. I found the error anyway. Although I posted it with ui:remove, the tests I did with ajaxSingle  true where with


              <c:forEach>



              . Using ui:repeat and ajazSingle  true in my commandLink worked as expected... Bad thing mixing components and tags, I guess...


              Thank you!

              • 4. Re: a4j:commandLink calling all actions in xhtml!!
                Jose Antonio Da Rocha Padilla Newbie

                Hi,


                You see, you'd better use a4j:repeat instead of ui:repeat, c:forEach, ... not only because it allows you to use AJAX but it's the way to avoid mixing families, then, just using a4j:repeat and the ajaxSingle true you have a good solution to your problem.