JSF生命周期 - selectonemenu

时间:2012-02-03 18:41:59

标签: jsf lifecycle

我的行为是我不理解的选择菜单。我会试着解释一下,想知道是否有人知道发生了什么。我正在使用JSF2和glassfish3。 我的xhtml代码如下:

<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>

我使用绑定,因为取决于selectOneMenu值,我将呈现一些其他组件,但现在这超出了范围。命令按钮用于提交。 ompleFamiliesTemplate()返回一个选择项列表。 支持bean是:

@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 !!");
}

我放了一些System.out.println来跟随对不同函数的调用,cetBacking1 bean构造函数和ompleFamiliesTemplate()以及valueChangeListener。 第一次在服务器日志中加载页面时,将显示下一条消息:

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

调用bean的{}函数,它调用cetBacking1.ompleFamiliesTemplate,第二个cetBacking1.ompleFamiliesTemplate由f:selectItems调用。它按预期工作。现在我更改了selectOneMenu的值,并在日志中显示:

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

最后一次调用cetBacking1.ompleFamiliesTemplate我认为这是由f:selectItems调用的。但是我不知道为什么在开始时两次调用cetBacking1.ompleFamiliesTemplate然后两次调用cetBacking1.listenerFamilia。 但接下来对我来说更令人惊讶。我再次更改selectOneMenu并在日志中显示:      信息:cetBacking1.ompleFamiliesTemplate !!!!!!      信息:cetBacking1.ompleFamiliesTemplate !!!!!!      信息:cetBacking1.listenerFamilia:3      信息:cetBacking1.listenerFamilia:3      信息:cetBacking1.listenerFamilia:3      信息:cetBacking1.ompleFamiliesTemplate !!!!!!

cetBacking1.ompleFamiliesTemplate在开始时被调用两次,但是监听器被调用三次。每次我更改selectOneMenu时,都会再次调用侦听器。如果我将selectOneMenu值更改两次,则日志如下:

 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   !!!!!!

问题是为什么在监听器执行之前更改selectOneMenu值时会调用cetBacking1.ompleFamiliesTemplate两次。为什么第一次更改selectOneMenu值时,侦听器执行两次,然后每次更改值时再执行一次。

提前致谢

2 个答案:

答案 0 :(得分:1)

在JSF中,可以在单个请求中多次调用getter。这是一个很好的答案:Why JSF calls getters multiple times

答案 1 :(得分:0)

一个月前,我遇到了同样的问题。 解决方案是,SessionScope和绑定不兼容。

您必须删除jsf页面中的绑定,一切正常。 要填充SelectCombo,您可以将List<SelectItem>与项目一起使用。