views:

385

answers:

3

Hello,

My managed bean :

public List<String> getLiQuickNav(){

 System.out.println("I'm here...");

 List<String> l = new ArrayList<String>();
 l.add("toto");
 l.add("tata");
 l.add("titi");
 return l;
}

My forEach :

<c:forEach var="categorie" items="#{mainControleur.liQuickNav}">
 <h:outputLabel value="${categorie}"/>
</c:forEach>

My output stream :
I'm here...
I'm here...
I'm here...
I'm here...

As you can see "getLiQuickNav( )" is call 4times by my ForEach. But I just wan't to call "getLiQuickNav( )" one time... How to call it just one time ?

Bonus question: Why "getLiQuickNav( )" is call 4time whereas I have only 3item "tata,titi,toto" ?

Thank's

+3  A: 

You can't control the number of times that getLiQuickNav() is called - consider caching your list so it isn't rebuilt between calls.

private List<String> l;

public List<String> getLiQuickNav()
{
     if ( l == null )
     {
          System.out.println("I'm here...");

          l = new ArrayList<String>();
          l.add("toto");
          l.add("tata");
          l.add("titi");
     }
     return l;
}

As well you should be using <ui:repeat/> rather than <c:forEach/>. See this blog entry for why.

mtpettyp
I don't think something like above is good practice in general. There is no reason for lazy initialization of something with 3 items. Construct the list in the constructor or a static block.
GreenieMeanie
@GreenieMeanie - this is obviously a trivial example, chances are that the actual list data would *not* be available on object construction or static block initialization (i.e. if it was pulled from some external source such as a database). The answer was meant to illustrate that constructing the list should not be done on every call to getLiQuickNav().
mtpettyp
+2  A: 

Answer

You're reinitializing the state in a getter every time. That is meant to be an accessor, not a way to initialize state. Don't create the list in getLiQuickNav, create in a constructor or setter.

Bonus

The first time you call getLiQuickNav() you initialize the list, the reference to this list gets returned and stored in a scope to evaluate your expression (.liQuickNav) and then the getLiQuickNav() is called by convention 3 more times for each item in the list.

It should get called once if you return the same list every time. You're returning a new one every time.

cwash
+2  A: 

Getter's in Java (in any context, to include for Faces Managed Beans) should not generate anything - they should just return a value. Create the list before hand and return it.

GreenieMeanie