grid editor breaks when attribute is part of hashCode

I just figured out a strange behaviour regarding the grid editor while trying to implement a grid editor in buffered mode as described [here]
(https://vaadin.com/components/vaadin-grid/java-examples/grid-editor):

If a field (e.g. firstName) of the bean (e.g. Person) is bound to an editor field, it may not be used to calculate the bean’s hashCode().
Otherwise, editing the field will (apparently) cause the editor’s OpenListener and CloseListener methods to not find the row anymore, so the save and cancel buttons are not removed an the edit button is not displayed.

This is especially annoying, since the automated tools we use (lombok / eclipse) by default include all fields in the calculation of hashCode… :slight_smile:

The workaround is simply to not include the field when calculating hashCode.

I have found a solution. I am using ListDataProvider for max performance (inMemory).

@Override public int hashCode(){} in my @Entity class cause the grid not refresh correctly. The custom hashCode() makes DB object from different reads equal, so I don’t want to remove equals/hashCode.

My new objects entity @Id is generated on DB insert. The new hashCode is based on @Id and does not match the key in class KeyMapper in DataCommunicator.

Instead of creating unnecessary boilerplate beans I found that overriding DataProvider.getId(T item) was the solution. The trick was to bypass the entity hashCode using System.identityHashCode(item)

public class ListDataProviderIdentityHashCode<T> extends ListDataProvider<T> {

    public ListDataProviderIdentityHashCode(Collection<T> items) {
        super(items);
    }

    @Override
    public Object getId(T item) {
        return System.identityHashCode(item);
    }
}

If hashCode is removed same DB object gets: EQUAL=false

repository.findById(124L).ifPresent(o1 ->
                repository.findById(124L).ifPresent(o2 ->
                        System.err.format("EQUAL=%s", o1.equals(o2))));

BTW: Saving a grid.editor new row, findAll(), dataProvider.refreshAll(), when user double-click on another row to edit, cause event.getItem() to return the old item. Found a solution:

       grid.addItemDoubleClickListener(event -> {
            if (!editor.isOpen()) {
                dataProvider.getItems().stream()
                        .filter(item -> event.getItem().getId().equals(item.getId()))
                        .findFirst()
                        .ifPresent(item -> editor.editItem(item));
            }
        });