Binded CheckBoxGroup SelectionListener not fired on deselection

Hello Everyone,

I’m struggeling to detect the deselection of items in a CheckBoxGroup that is binded to a bean. Here is a simplified example:

I have a class
Person
:

[code]
package com.vaadin.test;

import java.util.Date;
import java.util.Set;

public class Person {

private String name;
private Set<Tag> tags;

public Person(String name) {
    super();
    this.name = name;
}

public String getName() {
    return this.name;
}

public void setName(String name) {
    this.name = name;
}

public Set<Tag> getTags() {
    return tags;
}

public void setTags(Set<Tag> tags) {
    this.tags = tags;
}

}
[/code]An object of the class “Person” can have many Tags. The class
Tag
looks like this:

[code]
package com.vaadin.test;

public class Tag {

private String name;

public Tag(String name) {
    super();
    this.name = name;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@Override
public String toString() {
    return name;
}

@Override
public boolean equals(Object obj) {
    if (obj != null && obj.getClass().equals(Tag.class)) {
        return ((Tag) obj).getName().equals(this.getName());
    }
    return super.equals(obj);
}

}
[/code]I created a simple UI with a TextField, a CheckBoxGroup and a Binder:

[code]
package com.vaadin.test;

import java.util.HashSet;
import java.util.Set;

import com.vaadin.annotations.Theme;
import com.vaadin.data.Binder;
import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.CheckBoxGroup;
import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@Theme(“valo”)
public class TestUI
extends UI {

private static final long serialVersionUID = 1L;

@Override
protected void init(VaadinRequest request) {

    Person person = new Person("Marcus");
    person.setTags(new HashSet<Tag>() {{ add(new Tag("Foo")); add(new Tag("Bar")); }});

    Binder<Person> binder = new Binder<>(Person.class);

    TextField name = new TextField();
    binder.bind(name, Person::getName, Person::setName);

    CheckBoxGroup<Tag> tags = new CheckBoxGroup<>();
    tags.setItems(new HashSet<Tag>() {{ add(new Tag("Foo")); add(new Tag("Bar")); add(new Tag("Test")); }});
    tags.addSelectionListener(e -> {

        Set<Tag> selectedTags = e.getAllSelectedItems();
        Set<Tag> addedTags = e.getAddedSelection();
        Set<Tag> newTags = e.getNewSelection();
        Set<Tag> oldTags = e.getOldSelection();
        Set<Tag> removedTags = e.getRemovedSelection();
    });
    binder.bind(tags, Person::getTags, Person::setTags);

    this.setContent(new VerticalLayout(new Label("Hello Vaadin!"), name, tags));
  
    binder.setBean(person);
}

}
[/code]The result looks like this:

When I select and/or deselect the CheckBox “Test” the SelectionListener of the CheckBoxGroup gets fired and I can deal with the changed selection. However if I deselect and/or (re)select one of the CheckBoxes “Bar” or “Foo” the SelectionListener is not fired.

How can I deal with the deselction of preselected CheckBoxes in a CheckBoxGroup that is binded to a Bean?

Thanks in advance.

After posting this question on Stack Overflow as well I received an answer, which is the solution for my problem. I have to override the “hashCode” method in the
Tag
class. The class
Tag
looks like this now:

package com.vaadin.test;

public class Tag {

    private String name;

    public Tag(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;

        Tag tag = (Tag) obj;

        return this.name.equals(tag.getName());
    }

    @Override
    public int hashCode() {
        return this.name.hashCode();
    }
}