InstanceContainer loading-time differences

Jmix version: 2.2.1.1
Jmix Studio plugin version: 2.2.1-233
IntelliJ IDEA 2023.3.6 (Community Edition)
Build #IC-233.15026.9, built on March 21, 2024
Runtime version: 17.0.10+1-b1087.23 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
GC: G1 Young Generation, G1 Old Generation
Kotlin: 233.15026.9-IJ
java 17.0.4 2022-07-19 LTS
Java™ SE Runtime Environment (build 17.0.4+11-LTS-179)
Java HotSpot™ 64-Bit Server VM (build 17.0.4+11-LTS-179, mixed mode, sharing)
Operating System: macOS 14.4.1 (23E224)
Metal Rendering: ON
File System: Case-Sensitive Journaled HFS+ (APFS)
Browser: Safari - Version 17.4.1 (19618.1.15.11.14)
Database: PostgreSQL 13

Hello Jmix Team

While implementing my workaround for the problem situation described in this post Flow UI <select/> component setItems() method sets value to null, I discovered that the InstanceContainer initialization in my DetailView is different depending upon the entity’s state. This is now causing me to rework some of my view logic again, which is frustrating and time consuming.

I want to know if this is a bug or by design?

I will explain the chronology of what is happening with two use cases.

My DetailView descriptor defines…

        <instance id="perfSearchDc"
                  class="com.company.nf.entity.search.search"
                  fetchPlan="_base">
            <loader/>
        </instance>

My DetailView controller has the following methods involved:

public void onInit(final InitEvent event) {...}

public void onCreateEditPerfSearch(final Category category) {...}

public void onBeforeShow(final BeforeShowEvent event) {...}

Use Case CREATE - new entity instance creation and editing in the DetailView

From the list view I execute this upon CREATE:

        PerfSearch perfSearch = metadata.create(PerfSearch.class);

        DialogWindow<PerfSearchDetailView> dialogWindow = dialogWindows.detail(this, PerfSearch.class)
                .withViewClass(PerfSearchDetailView.class)
                .editEntity(perfSearch)
                .build();

        dialogWindow.getView().onCreateEditPerfSearch(perfSearch.getCategory());
        dialogWindow.open();

build() causes onInit() to be called - perfSearchDc item count = 0

onCreateEditPerfSearch() is called - perfSearchDc item count = 1, the new instance has been loaded into the InstanceContainer

open() causes onBeforeShow() to be called - perfSearchDc item count = 1

Use Case EDIT - existing entity instance editing in the DetailView

From the list view I execute this upon EDIT:

        PerfSearch perfSearch = searchesDataGrid.getSingleSelectedItem();

        DialogWindow<PerfSearchDetailView> dialogWindow = dialogWindows.detail(this, PerfSearch.class)
                .withViewClass(PerfSearchDetailView.class)
                .editEntity(perfSearch)
                .build();

        dialogWindow.getView().onCreateEditPerfSearch(perfSearch.getCategory());
        dialogWindow.open();

build() causes onInit() to be called - perfSearchDc item count = 0

onCreateEditPerfSearch() is called - perfSearchDc item count = 0, the existing instance has NOT been loaded into the InstanceContainer

open() causes onBeforeShow() to be called - perfSearchDc item count = 1

As you can see, the code that opens my DetailView is identical but the InstanceContainer perfSearchDc is loaded at different times. Why?

I can work around this situation by adding…

public void onInitEntity(final InitEntityEvent<PerfSearch> event) {...}

which is called before the new entity is added to the InstanceContainer and removing…

dialogWindow.getView().onCreateEditPerfSearch(perfSearch.getCategory());

for the CREATE use case, and doing the initialization that is in my onCreateEditPerfSearch() method inside onInitEntity() additionally but I then have more code to maintain.

Konstantin mentioned more detailed lifecycle documentation here Jmix 2.x.x "Opening Dialog Windows" documentation - additional information needed - #3 by krivopustov and this is really necessary in order to understand all of these details.

Thanks in advance for your feedback and support.

Best regards
Chris

You can check StandardDetailView::setupEntityToEdit(T entityToEdit). There’s a check if entity is new (not saved in db yet).

If entity is new it is setted in InstanceContainer immediately.

Otherwise this method sets entity id to InstanceLoader, to be loaded with corresponding fetchPlan.

Most likely you are using <dataLoadCoordinator auto="true"/> in editor. It adds triger for InstanceLoader to load entity in BeforeShowEvent

@yarik1706

Hello Ярослав

Thank you for the feedback and your quick response. I had assumed that the entity was copied directly from my ListView’s Collection and not fetched again from the database when the DetailView is built and opened, since the entity had not been modified in the DB. Therefore, I did not expect any difference in the behavior. And yes, I do have <dataLoadCoordinator auto="true"/> in my descriptor. I will have a closer look at StandardDeatailView::setupEntityToEdit(T entityToEdit) and the fetch as soon as possible.

Best regards
Chris