Обновление GroupTable без перезагрузки страницы

Привет!
У меня есть GroupTable, одна из колонок которой генерируется при помощи метода .addGeneratedColumn();
Значения этой колонки задаются из коллекции, которую я могу обновлять при помощи EventListener.
Вопрос в следующем: могу ли я обновлять GroupTable (или только генерируемую колонку) без перезагрузки всей страницы динамически?

GroupTable наследует Table. Там есть метод repaint()
image

Привет! Спасибо за ответ. Я думал в этом направлении , попробую обьяснить ход своих действий:
У меня есть вот такая таблица:
image
Колонка “Непрочитанные” генерируется здесь при помощи .addGeneratedColumn(). Значения для этой колонки лежат в коллекции countersDc. При изменениях этой коллекции при нажатии на любой из элементов группировки (+) значения непрочитанных сообщений меняются правильно на переданные в коллекцию. Я пытаюсь на данный момент сделать так, чтоб таблица перерисовывалась на экране без какого-либо вмешательства пользователя.
Я написал метод для обновления по event изменения этой коллекции:
image
При использовании этого метода я ловлю exception io.jmix.ui.executor.IllegalConcurrentAccessException: UI Shared state was accessed from a background thread
Далее я решил использовать uiAccessor:
image
Метод отрабатывает успешно, однако в UI сама таблица не обновляется , а появляется лишь бесконечный длящийся прогрессбар. При обновлении страницы значения в необходимых полях обновляются верно.
Буду благодарен за любую помощь

Весь код класса:

Спойлер

@Slf4j
@UiController(“Chat.browse”)
@UiDescriptor(“chat-browse.xml”)
@LookupComponent(“chatTable”)
public class CompanyChat extends StandardLookup {
@Autowired private GroupTable chatTable;
@Autowired private CollectionLoader companiesDl;
@Autowired private UiComponents uiComponents;
@Autowired private BrowserFrame chatFrame;
@Autowired private CurrentAuthentication currentAuthentication;
@Autowired private Messages messages;
@Autowired private FirestoreService firestoreService;
@Autowired private ChatUrlService chatUrlService;
@Autowired private CollectionContainer countersDc;
@Autowired private BackgroundWorker backgroundWorker;
private UIAccessor uiAccessor;

@Subscribe
public void onInit(InitEvent event) {
    uiAccessor = backgroundWorker.getUIAccessor();
    getCollectionChangeEvent();
    countersDc.setItems(firestoreService.getAllCounters());
    addGeneratedUnreadMessageColumn();
}

@Subscribe
public void onBeforeShow(BeforeShowEvent event) {
    UserDetails user = currentAuthentication.getUser();
    if (user instanceof Accountant) {
        companiesDl.setParameter("accountant", user);
    }

    companiesDl.load();
    chatTable.expandAll();
}

private void addGeneratedUnreadMessageColumn() {
    chatTable.addGeneratedColumn(messages.getMessage("kz.advance.onlinebuhgalteria.screen.company.chat/unread"), entity -> {
        var accountantCounter = countersDc.getItems()
                                          .stream()
                                          .filter(o -> o.getId()
                                                        .equals(entity.getUser()
                                                                      .getId()
                                                                      .toString()))
                                          .map(o -> o.getCounters()
                                                     .get("accountantCounter"))
                                          .map(o -> o == null ? 0L : o)
                                          .findFirst();

        var label = uiComponents.create(Label.TYPE_LONG);
        label.setValue(accountantCounter.orElse(0L));
        return label;
    });
}

private void getChatFrame(CompanyUser user, UUID companyId) {
    var chatUrl = chatUrlService.getUrl(user, companyId);
    chatFrame.setSource(UrlResource.class)
             .setUrl(chatUrl);
}

@Subscribe("chatTable")
public void onChatTableSelection(Table.SelectionEvent<CompanyUserLink> event) {
    var iterator = event.getSelected()
                        .iterator();

    if (iterator.hasNext()) {
        chatFrame.setVisible(true);
        var companyUser = iterator.next();
        getChatFrame(companyUser.getUser(), companyUser.getCompany()
                                                       .getId());
    } else {
        chatFrame.setVisible(false);
    }
}

@Subscribe(id = "countersDc", target = Target.DATA_CONTAINER)
public void onCountersDcCollectionChange(CollectionContainer.CollectionChangeEvent<Counter> event) {
    uiAccessor.access(() -> {
        chatTable.repaint();
    });
}

private void getCollectionChangeEvent() {
    var firestore = FirestoreClient.getFirestore();
    var countersCollection = firestore.collection("counters");

    countersCollection.addSnapshotListener((value, error) -> {
        countersDc.setItems(value.getDocuments()
                                 .stream()
                                 .map(o -> o.toObject(Counter.class))
                                 .collect(Collectors.toList()));
    });
}

}

Вы не пробовали uiAccessor.accessSynchronously? Сложно сказать почему прогрессбар не заканчивается. Мб где-то лок процесса произошел…

Возможно uiAccessor.access лучше перенести в addSnapshotListener

Спасибо за ответ!
Перенес uiAccessor.access в addSnapshotListener
image
ловлю com.vaadin.v7.ui.Table$CacheUpdateException: Error during Table cache update. Additional causes not shown. В cause - java.lang.IllegalStateException: Authentication is not set. Use SystemAuthenticator in non-user requests like schedulers or asynchronous calls.
Использую SystemAuthenticator:
image
Уже не получаю никаких экспешнов, но получаю бесконечный прогрессбар, таблица не обновляется. Не работают оба варианта, ни .access, ни .accessSynchronously

Сработал такой вариант. Огромное спасибо за помощь!
image