Bug - nested entity EntityLoadingEvent not triggered if fetchplan on outer entity is _base

I have a localizedStringEntity for storing user translated values, I use this in other entities

eg.

@JmixEntity
@Table(name = "OCTO_COUNTRY", uniqueConstraints = {
        @UniqueConstraint(name = "IDX_OCTO_COUNTRY_UNQ", columnNames = {"TENANT_ID", "ISO_CODE", "DELETE_TS"})
})
@Entity(name = "octo_Country")
public class Country extends StandardTenantEntity {
    private static final long serialVersionUID = 548912591307638405L;

    @InstanceName
    @NotNull
    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "NAME_ID", nullable = false)
    protected LocalizedString name;

and

@JmixEntity
@Table(name = "OCTO_DOSSIER_TYPE")
@Entity(name = "octo_DossierType")
public class DossierType extends StandardTenantEntity {
    private static final long serialVersionUID = 8465221778783351503L;

    @InstanceName
    @NotNull
    @Composition
    @OnDelete(DeletePolicy.CASCADE)
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "NAME_ID")
    protected LocalizedString name;

The entities are identical, I have a browsescreen for each with a datacollection and using autoload.

    <data readOnly="true">
        <collection id="countriesDc" class="eu.octorilla.contact.model.Country" fetchPlan="_base">
            <loader id="countriesDl">
                <query>
                    <![CDATA[select e from octo_Country e]]>
                </query>
            </loader>
        </collection>
    </data>
        <collection id="dossierTypesDc" class="eu.octorilla.dossier.domain.DossierType" fetchPlan="_local">
            <loader id="dossierTypesDl">
                <query>
                    <![CDATA[select e from octo_DossierType e]]>
                </query>
            </loader>
        </collection>
    </data>

I have an entity listener to get the user’s language so I know what string to display

@Component
@AllArgsConstructor
public class LocalizedStringEntityListener {
    public static final String NAME = "localizedStringEntityListener";


    private final CurrentUserRetriever currentUserRetriever;

    @EventListener
    void onLoad(EntityLoadingEvent<LocalizedString> event) {
        event.getEntity().setCurrentLanguage(currentUserRetriever.getCurrentSessionLanguage());
    }
}

When the fetchplan is _base the entityListener is not invoked, when it is _local it does work

EDIT: it looks like not specifying a fetchplan also gives the same issue

Hello,

thank you for reporting. Can you tell if this works with inline fetch plans?

        <collection id="dossierTypesDc"
                    class="com.company.fetchplantest.entity.DossierType">
            <fetchPlan extends="_base">
            </fetchPlan>
            <loader id="dossierTypesDl">
                <query>
                    <![CDATA[select e from DossierType e]]>
                </query>
            </loader>
        </collection>

EDITED: so it depends where the fetchplan is defined :thinking:

it works BUT …

This was by far the simplest sample I could give. In my application, I have screens that are much more complex where the LocalizedString can be used at pretty much every level including deep nesting in the fetchplans.

I got everything working (I hope) for now. But it is completely unclear to me when it works and when it doesn’t. It’s also very fragile.

I’m solving it by basically brute forcing combinations in the fetch plans until it works.

Can you confirm that this is a bug and that it will be solved? At least I can stop trying to reverse engingeer the logic.

thx,
Tom

As an example of complex fetchplan.
(This should probably be simplified and split over more components/screens, but that is beside the question)

        <instance id="dossierDc" class="eu.octorilla.dossier.domain.Dossier">
            <fetchPlan extends="_local">
                <property fetchPlan="_base" name="dossiertype"/>
                <property fetchPlan="_local" name="logboek">
                    <property fetchPlan="_base" name="logEntries"/>
                </property>
                <property fetchPlan="_local" name="expertises">
                    <property fetchPlan="_local" name="address">
                        <property name="country" fetchPlan="_local"/>
                    </property>
                    <property name="dossier" fetchPlan="_local">
                        <property name="parties" fetchPlan="_local">
                            <property name="company" fetchPlan="_local">
                                <property name="address" fetchPlan="_local">
                                    <property name="country" fetchPlan="_local"/>
                                </property>
                            </property>
                        </property>
                    </property>
                </property>
                <property fetchPlan="_base" name="assignee"/>
                <property fetchPlan="_local" name="parties">
                    <property fetchPlan="_local" name="capacity"/>
                    <property fetchPlan="_base" name="contactPerson"/>
                    <property fetchPlan="_local" name="company">
                        <property name="address" fetchPlan="_local"/>
                    </property>
                </property>
                <property fetchPlan="_local" name="category"/>
                <property name="dossierPrestations" fetchPlan="_base">
                    <property name="prestationSets" fetchPlan="_local">
                        <property name="bookedOn" fetchPlan="_base"/>
                    </property>
                </property>
            </fetchPlan>

@t.musin
this is a pretty big issue for us. any news on this?

@t.musin ??

Hi,

It looks like a wrong behavior. I’ve created an issue for this.

@gorbunkov thank you for your answer and for creating a ticket.

As you already mentioned in the ticket, it should be fixed in 1.x as well. For me this really is an issue, part of my architecture depends on this, and due to the fact that is so low level there is no clear workaround or alternative.