Search code examples
jsfselectonemenuvaluechangelistenerselectbooleancheckbox

Value of <h:selectBooleanCheckbox> is not updated according to backing bean value


I'm using JSF2 and Tomcat server. I programmed a simple example in which:

  • User Selects a faculty from "h:selectOneMenu"
  • Upon selection, the value of "h:inputText" is changed to "odd" or "even" based on facultyNo
  • Also, upon selection, the value of "h:selectBooleanCheckBox" is changed to "checked" if facultyNo is even and "not checked" if facultyNo is odd

Everything works fine for "h:inputText". On the other hand, the value of "h:selectBooleanCheckBox" does not change. Why is this happening?

By the way, the use of boolean value inside a HashMap is intentional because the project I'm working on has lots of boolean values in a HashMap. So, replacing the Hashmap with a simple boolean property and using a getter and a setter for it is definitely not a solution for my case.

The code for the xhtml page is below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
     <head>       
        <title>Dummy Title</title>        
     </head>    
     <body>
        <h:form>
            <label for="faculty">Faculty</label>
            <h:selectOneMenu id="faculty" value="#{test.selectedFaculty}" converter="faccon" valueChangeListener="#{test.facultyChange}" onchange="submit()">
                <f:selectItems value="#{start.app.faculties}"/>                      
            </h:selectOneMenu>                                  
            <h:selectBooleanCheckbox id="mycheck" value="#{test.x.get(0)}"></h:selectBooleanCheckbox>
            <h:outputText value="#{test.res}"></h:outputText>
            <h:commandButton value="Save" action="#{test.saveChoices}" />
        </h:form>           
    </body>
</html>

The code for the backing bean is below

import java.io.Serializable;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ValueChangeEvent;
import com.myWork.Application;
import com.myWork.Faculty;

@ManagedBean(name="test")
@RequestScoped
public class TestBean implements Serializable
{
    private HashMap<Integer,Boolean> x;
    private String res;
    private Faculty selectedFaculty;

    @PostConstruct
    public void init(){
        Application app = Application.getInstance();
        selectedFaculty = app.getFaculties()[0];
        x = new HashMap<Integer, Boolean>();
        if (selectedFaculty.getFacultyNo()%2==0)
        {
            x.put(0, true);
            res = "even";
        }
        else
        {
            x.put(0, false);
            res = "odd";
        }
    }

    public HashMap<Integer,Boolean> getX() {
        return x;
    }


    public void setX(HashMap<Integer,Boolean> x) {
        this.x = x;
    }

    public Faculty getSelectedFaculty() {
        return selectedFaculty;
    }

    public void setSelectedFaculty(Faculty selectedFaculty) {
        this.selectedFaculty = selectedFaculty;
    }   

    public String getRes() {
        return res;
    }

    public void setRes(String res) {
        this.res = res;
    }

    public void facultyChange(ValueChangeEvent e){
        Faculty fac = (Faculty) e.getNewValue();
        if (fac.getFacultyNo()%2==0)
        {           
            x.put(0, true);
            res = "even";
        }
        else
        {
            x.put(0, false);
            res = "odd";
        }
    }   

    public String saveChoices(){        
        return "test";
    }
}

Any help is greatly appreciated.


Solution

  • Actually your problem is not related to JSF, it is related to EL. in your case, EL treat you map keys as long not int, so you should change your map to be:

    HashMap<Long, Boolean> map = new HashMap<>();
    

    and set the key values as follows :

        map.put(0L, false);
        map.put(1L, true);
    

    to force it to be auto-boxed to long.

    Note: the problem described in detailed in the following question : EL access a map value by Integer key