2
votes

Good day. In my project, I have a List of custom objects which I use in my PrimeFaces p:selectCheckboxMenu. I use a converter for this class. The dropdown looks great and if I select an item from the list, the "chips" display correctly. However, if I load the selected list on initialization, the selected "chip" shows a class reference (com.test.Characteristic@56e76bff) instead of the value of the object. I would expect it to show the return value of getAsString from the converter. What am I doing wrong?

Example of what I am seeing

On to the code for this: The custom object

    public class Characteristic {
    public Characteristic() {
        super();
    }
    private String key;
    private String value;
    private String type;

    public Characteristic(String key, String value, String type) {
        this.key = key;
        this.value = value;
        this.type = type;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

The Converter:

    @FacesConverter(value = "characteristicConverter")
    public class CharacteristicConverter implements Converter {
        public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
            return new Characteristic("testKey", value, "testType");
        }

        public String getAsString(FacesContext fc, UIComponent uic, Object object) {
            if (object == null) {
                return "";
            }
            if (object instanceof Characteristic) {
                Characteristic cha = (Characteristic) object;
                String name = cha.getValue();
                System.out.println("In the converter. Returning " + name);                
                return name;
            } else {
                throw new ConverterException(new FacesMessage(object + " is not a Characteristic"));
            }
        }
    }

The System.out.prinln's in the converter display this when run:

In the converter. Returning char1value

In the converter. Returning char2value

In the converter. Returning char3value

In the converter. Returning char1value

The Bean:

@ManagedBean(name = "checkboxView")
public class CheckboxView {

    private List<Characteristic> allChars;
    private List<Characteristic> selectedChars;

    @PostConstruct
    public void init() {

        allChars = new ArrayList<Characteristic>();
        allChars.add(new Characteristic("char1key","char1value","test"));
        allChars.add(new Characteristic("char2key","char2value","test"));
        allChars.add(new Characteristic("char3key","char3value","test"));
        selectedChars = new ArrayList<Characteristic>();
        selectedChars.add(new Characteristic("char1key","char1value","test"));
    }

    public void setAllChars(List<Characteristic> allChars) {
        this.allChars = allChars;
    }

    public List<Characteristic> getAllChars() {
        return allChars;
    }

    public void setSelectedChars(List<Characteristic> selectedChars) {
        this.selectedChars = selectedChars;
    }

    public List<Characteristic> getSelectedChars() {
        return selectedChars;
    }
}

The page:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui">
    <h:head></h:head>
    <h:body>
        <h:form>
            <p:selectCheckboxMenu id="multiple" value="#{checkboxView.selectedChars}" label="Characteristics"
                                  multiple="true" filter="true" filterMatchMode="startsWith"
                                  converter="characteristicConverter">
                <f:selectItems value="#{checkboxView.allChars}" var="cha" itemLabel="#{cha.value}" itemValue="#{cha}"/>
            </p:selectCheckboxMenu>
        </h:form>
    </h:body>
</html>      
1
Does not using a filter make a difference? or not using multiple but e.g. the updateLabel? And what is your PF version?Kukeltje
@Kukeltje PrimeFaces version 6.1. I removed "filter" and "filterMatchMode" and I got the same string "com.test.Characteristic@56e76bff". If I remove multiple, it puts the value of label in the spot instead. I'm afraid I don't know what you mean by updateLabel...Sam Donato
@Kukeltje I looked at the docs and added updateLabel="true" and I got the same bad result.Sam Donato
Can you (just for testing this issue) try 6.2 (good thing to always to, try the latest)Kukeltje
@Kukeltje It is the same with 6.2Sam Donato

1 Answers

1
votes

I suspect it has to do with comparing the Characteristics in the list with the pre-selected one (since in the visual list it is not selected either and it would most likely fail with an h:selectManyCheckbox as well). You can try changing

@PostConstruct
public void init() {

    allChars = new ArrayList<Characteristic>();
    allChars.add(new Characteristic("char1key","char1value","test"));
    allChars.add(new Characteristic("char2key","char2value","test"));
    allChars.add(new Characteristic("char3key","char3value","test"));
    selectedChars = new ArrayList<Characteristic>();
    selectedChars.add(new Characteristic("char1key","char1value","test"));
}

to

@PostConstruct
public void init() {

    allChars = new ArrayList<Characteristic>();
    Characteristic char1 = new Characteristic("char1key","char1value","test");
    Characteristic char2 = new Characteristic("char2key","char2value","test");
    Characteristic char3 = new Characteristic("char3key","char3value","test");
    allChars.add(char1);
    allChars.add(char2);
    allChars.add(char3);


    selectedChars = new ArrayList<Characteristic>();
    selectedChars.add(char1);
}

So the selected 'char1' is object wise identical to the one in the list. But even better would be to try to implement the equals and hash of the Characteristic explicitly.