Не обновляется отображение Kanban после повторной вставки итемов в контейнер

Здравствуйте! Версия 2.4.1, Idea 2024.3.

В продолжении с чата, повторюсь что при повторной вставке элементов в контейнер канбана не отображаются итемы.

Код KanbanEntity:

Спойлер
@JmixEntity
@Table(name = "KANBAN_ENTITY", indexes = {
        @Index(name = "IDX_KANBAN_ENTITY_SUGGESTION", columnList = "SUGGESTION_ID")
})
@Entity
public class KanbanEntity {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "TEXT", nullable = false, length = 50)
    @NotNull
    private String text;

    @Column(name = "STATUS", nullable = false, length = 100)
    @NotNull
    private String status;

    @Column(name = "CREATION_DATE")
    private LocalDate creationDate;

    @Column(name = "DEPARTMENT_NUMBER", length = 50)
    private String departmentNumber;

    @OnDeleteInverse(DeletePolicy.CASCADE)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SUGGESTION_ID")
    private Suggestion suggestion;

Код класса экрана для отображения kanban (лишнее убрал).

Спойлер
public class KanbanListView extends StandardView {

    @Autowired
    private KanbanService kanbanService;
    @ViewComponent
    private CollectionContainer<KanbanEntity> kanbanEntitiesDc;
    @ViewComponent
    private TypedDatePicker<Comparable> startDate;
    @ViewComponent
    private TypedDatePicker<Comparable> endDate;
    @ViewComponent
    private TypedTextField<Object> departmentNumberField;
    @ViewComponent
    private Kanban<KanbanEntity> kanban;

    @Subscribe
    public void onInit(final InitEvent event) {

        kanbanEntitiesDc.setItems(kanbanService.createAndGetCurrentSuggestionByKanban(
                null, null, null));

        kanban.getI18n().withEmpty("Нет предложений");

    }

    @Subscribe(id = "approveButton", subject = "clickListener")
    public void onApproveButtonClick(final ClickEvent<JmixButton> event) {

        kanbanEntitiesDc.setItems(kanbanService.createAndGetCurrentSuggestionByKanban(
                startDate.getValue(),
                endDate.getValue(),
                departmentNumberField.getValue()));

    }

    @Subscribe(id = "resetButton", subject = "clickListener")
    public void onResetButtonClick(final ClickEvent<JmixButton> event) {

        startDate.setValue(null);
        endDate.setValue(null);
        departmentNumberField.setValue("");

        kanbanEntitiesDc.setItems(kanbanService.createAndGetCurrentSuggestionByKanban(
                startDate.getValue(),
                endDate.getValue(),
                departmentNumberField.getValue()));

    }

Имплементация KanbanService (лишнее удалил):

Спойлер
@Component
public class KanbanServiceImpl implements KanbanService {

    @Autowired
    private UnconstrainedDataManager dataManager;
    @Autowired
    private StatisticService statisticService;
    @Autowired
    private FetchPlans fetchPlans;

    private Map<UUID, KanbanEntity> kanbanCache = new ConcurrentHashMap<>();

    @PostConstruct
    private void buildKanbanCache() {

        List<KanbanEntity> kanbans = dataManager.load(KanbanEntity.class)
                .all().list();

        kanbans.forEach(dataManager::remove);

        List<Suggestion> suggestions = dataManager.load(Suggestion.class)
                .all()
                .fetchPlan(fetchPlans.builder(Suggestion.class)
                        .addAll("creationDate", "number", "status", "creatorDepartmentNumber", "id")
                        .build())
                .list();

        kanbans.clear();

        for (Suggestion suggestion : suggestions) {

            KanbanEntity kanbanEntity = dataManager.create(KanbanEntity.class);

            kanbanEntity.setStatus(suggestion.getStatus());
            kanbanEntity.setText(suggestion.getNumber());
            kanbanEntity.setSuggestion(suggestion);
            kanbanEntity.setDepartmentNumber(suggestion.getCreatorDepartmentNumber());
            kanbanEntity.setCreationDate(suggestion.getCreationDate());

            kanbans.add(kanbanEntity);

        }

        SaveContext saveContext = new SaveContext();
        saveContext.saving(kanbans);

        EntitySet entitySet = dataManager.save(saveContext);

        entitySet.getAll(KanbanEntity.class)
                .forEach(x -> kanbanCache.put(x.getSuggestion().getId(), x));

    }

    @Override
    public List<KanbanEntity> createAndGetCurrentSuggestionByKanban(LocalDate startDate,
                                                                    LocalDate endDate,
                                                                    String departmentNumber) {

        if (startDate == null) {
            startDate = statisticService.getMinSuggestionDate();
        }

        if (endDate == null) {
            endDate = LocalDate.now().plusDays(1);
        }

        LocalDate finalStartDate = startDate;
        LocalDate finalEndDate = endDate;

        Comparator<KanbanEntity> comparator = (x1, x2) -> x2.getCreationDate().compareTo(x1.getCreationDate());

        return kanbanCache.values()
                .stream()
                .filter(x -> (x.getCreationDate().isAfter(finalStartDate)
                        && x.getCreationDate().isBefore(finalEndDate)))
                .filter(x -> (!StringUtils.hasText(departmentNumber)
                        || x.getDepartmentNumber().equalsIgnoreCase(departmentNumber)))
                .sorted(comparator)
                .toList();

    }

По коду наверное ± понятно что происходит, но на всякий по шагам.

  1. Приложение стартует, отрабатывает аннотация и метод void buildKanbanCache() сервиса KanbanServiceImpl, который удаляет из базы все KanbanEntity и создаёт новые на основе имеющихся сущностей Suggestion и кладёт их в базу и в Map<UUID, KanbanEntity> kanbanCache (UUID это id Suggestion, заготовка под обновление кэша при создании/измении главной сущности).
  2. При открытии экрана в init-методе вызывается метод сервиса createAndGetCurrentSuggestionByKanban(null, null, null), который отдаёт коллекцию, коллекция помещается в контейнер и экран открывается. На этом этапе отображается полный список всех имеющихся kanbanEntity.
  3. Далее если выбрать какое-либо значение в полях экрана (текстовое или дату) и нажать кнопку “Подтвердить”, то данные записываются в поля в java-классе и вызывается сервис с данными из этих полей. Например выбираю дату “с” 01.11.2024 и нажимаю принять. Сервис отрабатывает и возвращает отфильтрованную коллекцию, но обновляются только индикаторы количества записей по статусам, но сами “значки” или “карточки” на которые можно кликнуть, нет.

Вот собственно такая проблемка, перепробовал много вариантов уже: убирал fetch-план при выгрузке Suggestion, делал загрузку KanbanEntity прямо из базы, а не из кеша и т.д., ничего не помагает в таком раскладе.
До этого работало, но там не было кеша и был немного другой алгоритм, если вкратце то метод createAndGetCurrentSuggestionByKanban удалял все KanbanEntity из базы, выгружал все Suggestion, создавал новые KanbanEntity, сохранял в базу и тут же отдавал результаты сохранения. Было удобно что не надо следить за обновлением Suggestion и всегда всё было относительно “динамически”, но сильно страдала производительность уже при 400+ записях.

Здравствуйте!

Удалось воспроизвести проблему. Пока не совсем ясно из-за чего не отображаются карточки, но воспроизвелось на большем кол-ве данных (например, сгенерировал 500 строк).

Создал задачу: Kanban stops rendering tasks after setting items · Issue #3996 · jmix-framework/jmix · GitHub, будем смотреть, спасибо что сообщили.