Search code examples
jsfmanaged-beanvaluechangelistener

Does the valueChangeListener method create a new bean instance each time?


I've a <p:selectOneMenu> with String entries and a valueChangeListener on it.

View:

<p:selectOneMenu value="#{myLdapEntry.oneMenuselectedValue}" effect="fade" style="font-size:12px;"
    valueChangeListener="#{myLdapEntry.menuValueChanged}">
    <f:selectItem itemLabel="" itemValue=""/>
    <f:selectItems value="#{treeBean.objclasslist}" var="objclass"
    itemLabel="#{objclass}" itemValue="#{objclass}" />
    <p:column>   
        #{o}  #{objclass}
    </p:column>
    <f:ajax event="change" render=":form:objclassAttrsValstab" />
</p:selectOneMenu>

Model:

List<String> objectClassList = new ArrayList<String>();

public void menuValueChanged(ValueChangeEvent vce) {
    String newValue = vce.getNewValue().toString();
    objectClassList.add(newValue);
    System.out.println(objectClassList);
}

I would like to remember every previously seledted item in the objectClassList. But the problem is that it always contains only the last selected item and not the items before that. I've even tried with a Vector instead of a List, but still have the same result.

I think that the valueChangeListener method creates a new bean instance each time so that the objectClassList is reinitialized each time.

Is this true? How is this caused and how can I solve it?


Solution

  • That can indeed happen if the bean is request scoped. Every HTTP request would then create a brand new bean instance. Simple as that. If you need to have the same bean instance while interacting on the same view, then it should be placed in the view scope instead.

    @ManagedBean
    @ViewScoped
    public class MyLdapEntry {
       // ... 
    }
    

    This problem is totally unrelated to whether you use valueChangeListener or not.

    See also:


    Unrelated to the concrete problem, the valueChangeListener isn't entirely the right place to perform business actions and model value manipulations. Rather use <p:ajax listener> instead of valueChangeListener (and <f:ajax>).

    <p:ajax listener="#{myLdapEntry.menuValueChanged}" update=":form:objclassAttrsValstab" />
    

    with

    public void menuValueChanged() {
        objectClassList.add(oneMenuselectedValue);
    }
    

    See also: