I am struggling while trying to update a BeanItemContainer backing a Table with a user selection.
This is my use case (please see the attached 2 files):
Server
[list]
Create a Table, backed by a BeanItemContainer.
Put an item into the beanItemContainer.
[/list]
User
[list]
Select the item in the table
Click “update container”
[/list]
Server
[list]
replace the item in the BeanItemContainer with an updated version being “equal” to the old one
(This simulates someone else updating Entities in the database. The equals method just takes the primary key into account.)
[/list]
User
[list]
Click “show item data”
[/list]
Server
[list]
display
(a) item data from BeanItemContainer
(b) item data from table selection (Table.getValue())
[/list]
My expectation : (a) and (b) should be both up to date and the same (object identity)
Result
the item from BeanItemContainer (a) has the changed (updated) item
the item from Table (b) still has the old (unchanged) item
they are NOT the same but equal
Isn’t Vaadin supposed to update the table selection when the backing container is updated?
What is the easiest possibility to fix this problem?
Did you figure it out? And please tell if you found some great way to do it
I think updating the actual item instead of replacing it would be a good place to start, but if that’s not possible I think you might need to just set the table value again. I doubt (do correct me if I’m wrong) the equals matters outside the moment when the table selects the item, after that it just points to an object and that object isn’t the one you wish it to be.
I had to add a really nasty hack to make that work:
Implement an ItemSetChangeListener which is added to the table.
final class UpdateTableSelectionOnItemSetChange<M> implements ItemSetChangeListener {
private final Table table;
UpdateTableSelectionOnItemSetChange(final Table table) {
super();
this.table = table;
}
@SuppressWarnings({ "PMD.SimplifyConditional", "rawtypes", "unchecked" })
@Override
public void containerItemSetChange(final ItemSetChangeEvent event) {
final Collection<M> itemIds = (Collection<M>)table.getContainerDataSource().getItemIds();
if (itemIds.isEmpty()) {
// a previously filled table is now empty ==> remove its value since its selection is outdated this also
// updates dependent forms via a resulting value change event
table.setValue(null);
} else {
final Object tableVal = table.getValue();
if (tableVal instanceof Collection && tableVal != null && !((Collection)tableVal).isEmpty()) {
final M selectedItemId = ((Collection<M>)tableVal).iterator().next();
// FIXME: needs to be adapted for multiselect tables
for (final M itemId : itemIds) {
if (itemId.equals(selectedItemId) && itemId != selectedItemId) {
table.setValue(null); // otherwise the next set value will be discarded since
// oldVal.equals(newVal)
table.setValue(Collections.singleton(itemId));
break;
}
}
}
}
}
}
Might be worth a shot, yes. I can see how that would be a useful feature for other users as well - and thanks for sharing your solution! Even nasty hacks can be useful Your solution is actually pretty close to what I was thinking about, but an example is always better. Anyway, I’m not sure how easy fix that would be, so better not count on it getting solved in near future. Generally speaking Table is the difficult one, so it might take a good while. Unless the problem is with BeanItemContainer itself, of course. I haven’t used that one much so I really can’t say. Have you tried other containers? SQLContainer might be worth checking out, unless you’ve already done so, and of course there are plenty of containers in add-ons, too. I’ve mostly dealt with JPAContainer lately, and JPA itself really has been an experience to get to know
Because I think I stepped into this or something similar and reported it as
#10993 . No reply yet… I solved it by resetting the selection every time the container is modified.