0

I have a behaviour that I don’t understand with a selectonemenu. I will try to explain it wondering if somebody know what’s happening. I am using JSF2 with glassfish3. My xhtml code is as follows:

<h:selectOneMenu  binding="#{cetBacking1.menuFamilies}"
                  valueChangeListener="#{cetBacking1.listenerFamilia}"
                  onchange="this.form.submit()">
   <f:selectItems value="#{cetBacking1.ompleFamiliesTemplate()}"></f:selectItems>
</h:selectOneMenu>
<h:commandButton value="Test" type="submit" action="#{cetBacking1.test()}">    </h:commandButton>

I use binding because depending on the selectOneMenu value I will render some other components but now this is out of scope. The command button is for the submit. ompleFamiliesTemplate() returns a list of selectitems. And the backing bean is:

@ManagedBean(name="cetBacking1")
@SessionScoped
public class cetBacking1 extends AbstractEntityAccessor implements Serializable {
private List<SelectItem> llistaFamilies = new ArrayList<SelectItem>();
private HtmlSelectOneMenu menuFamilies;
{
    System.out.println("cetBacking1.init");
    ompleFamiliesTemplate();
}


public void listenerFamilia(ValueChangeEvent event) {
    String novaFamilia = (String) event.getNewValue();
    System.out.println("cetBacking1.listenerFamilia: " + novaFamilia);
}

public List ompleFamiliesTemplate() {
    FacesContext context = FacesContext.getCurrentInstance();
    List<FamiliaTemplate> llistaFamiliestmp = new ArrayList<FamiliaTemplate>();
    System.out.println("cetBacking1.ompleFamiliesTemplate   !!!!!!");
    if (context.getExternalContext().getSessionMap().containsKey("LlistaFamilies")) {
        llistaFamiliestmp = (List<FamiliaTemplate>) context.getExternalContext().getSessionMap().get("LlistaFamilies");
        if (llistaFamilies.isEmpty()) {
            for (Iterator it = llistaFamiliestmp.iterator(); it.hasNext();) {
                FamiliaTemplate object = (FamiliaTemplate) it.next();
                llistaFamilies.add(new SelectItem(String.valueOf(object.getIdfamiliaTemplate()), object.getFamilia()));
            }
        }
    }
    return llistaFamilies;
}
public void submit() {
    System.out.println("cetBacking1.submit !!");
}

I put some System.out.println to follow the calls to the different functions, the cetBacking1 bean constructor and ompleFamiliesTemplate(), and the valueChangeListener. The first time the page is loaded in the server log appears the next messages:

INFO: cetBacking1.init
INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!

The {} function of the bean is called, it calls cetBacking1.ompleFamiliesTemplate and the second cetBacking1.ompleFamiliesTemplate is called by the f:selectItems. It works as expected. Now I change tha value of the selectOneMenu and in the log appears:

 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!

The last call to cetBacking1.ompleFamiliesTemplate I think that is called by f:selectItems. But I do not why is called twice at the beginning cetBacking1.ompleFamiliesTemplate and then twice the listener cetBacking1.listenerFamilia. But the next is more amazing for me. I change again the selectOneMenu and in the log appear: INFO: cetBacking1.ompleFamiliesTemplate !!!!!! INFO: cetBacking1.ompleFamiliesTemplate !!!!!! INFO: cetBacking1.listenerFamilia: 3 INFO: cetBacking1.listenerFamilia: 3 INFO: cetBacking1.listenerFamilia: 3 INFO: cetBacking1.ompleFamiliesTemplate !!!!!!

The cetBacking1.ompleFamiliesTemplate is called twice at the beginning as before but the listener is called three times. Each time I change the selectOneMenu the listener is called one more time. If I change the selectOneMenu value two times the log is as follows:

 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!! 
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.listenerFamilia: 1
 INFO: cetBacking1.listenerFamilia: 1
 INFO: cetBacking1.listenerFamilia: 1
 INFO: cetBacking1.listenerFamilia: 1
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.listenerFamilia: 2 
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.listenerFamilia: 2
 INFO: cetBacking1.ompleFamiliesTemplate   !!!!!!

The question is why cetBacking1.ompleFamiliesTemplate is called twice when I change the selectOneMenu value, before the listener execution. And why the listener is executed twice the first time I change the selectOneMenu value, and then one more time every time I change the value.

Thanks in advance

  • As Jeremiah answered, your concrete problem is that you did the business logic in a getter method. This is Wrong. Just a word of advice, if you're using JSF 2.x, do not focus too much on JSF 1.x targeted books/resources. Whatever you're trying to achieve can more easily be done with ``. – BalusC Feb 03 '12 at 19:07

2 Answers2

1

In JSF, getters can be called multiple times in a single request. Here's a good answer on this: Why JSF calls getters multiple times

Community
  • 1
  • 1
Jeremiah Orr
  • 2,620
  • 1
  • 18
  • 24
0

One Month ago i had the same problem. The solution is, that SessionScope and binding are not compatible.

You have to remove the binding in your jsf-page and everything works fine. To fill the SelectCombo you can use List<SelectItem> with items.

Tobi
  • 1,440
  • 1
  • 13
  • 26