EntityLoadingEvent omitted when accessing through entity relation

I have a question regarding EntityLoadingEvents (https://docs.jmix.io/jmix/data-access/entity-events.html#saving-loading-events).

I implemented such an event listener which resolves additional attribute data on loading an entity.

package com.company.app.demo.entity.customer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import io.jmix.core.event.EntityLoadingEvent;

@Component
public class CustomerEventListener
{
    @Autowired
    private ICustomerService customerService;

    @EventListener
    public void onCustomerLoading(final EntityLoadingEvent<Customer> anEvent)
    {
        customerService.loadTransientFieldsCurrent(anEvent.getEntity());
    }
}

That work’s as expected when using a standard lookup.

<collection id="customersDc" class="com.company.app.demo.entity.customer.Customer">
  <fetchPlan extends="_base"/>
  <loader id="customersDl">
    <query>
      <![CDATA[SELECT e FROM demo_Customer e]]>
    </query>
  </loader>
</collection>

It does not work, when the customer is accessed through another entity e.g. Order by accessing a method: Order#getCustomer().

package com.company.app.demo.entity.order;

import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

/* ... */

import io.jmix.core.entity.annotation.OnDeleteInverse;
import io.jmix.core.metamodel.annotation.JmixEntity;

/* ... */

@JmixEntity
@Entity(name = "demo_Order")
public class Order
{
    /* ... */

    @OnDeleteInverse(DeletePolicy.DENY)
    @JoinColumn(name = "CONSUMER_ID")
    @ManyToOne(fetch = FetchType.LAZY)
    private Customer customer;

    /* ... */

    public Customer getCustomer()
    {
        return customer;
    }

    /* ... */
}

Is that behavior intended?

Hi

EntityLoadingEvent is not published by the framework for the references. So you need to define separate listener for the Order entity and process its attribute.

@gaslov Thank you for answering.

I am going to try something like the following. There are several fetch plans loading Order entities. Some of them load the customer reference, some do not. I wonder how the performance impact will be.

Could you check, if the following will meet these considerations within the extended event listener draft:

package com.company.app.demo.entity.customer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import io.jmix.core.EntityStates;
import io.jmix.core.FetchPlan;
import io.jmix.core.FetchPlanProperty;
import io.jmix.core.event.EntityLoadingEvent;

import com.company.app.demo.entity.order.Order;

@Component
public class CustomerEventListener
{
    @Autowired
    private EntityStates entityStates;

    @Autowired
    private ICustomerService customerService;

    @EventListener
    public void onCustomerLoading(final EntityLoadingEvent<Customer> anEvent)
    {
        customerService.loadTransientFieldsCurrent(anEvent.getEntity());
    }

    @EventListener
    public void onOrderLoading(final EntityLoadingEvent<Order> anEvent)
    {
        final FetchPlan fetchPlan = entityStates.getCurrentFetchPlan(anEvent.getEntity());
        for (final FetchPlanProperty fpProp : fetchPlan.getProperties())
        {
            if (Objects.equals(fpProp.getName(), "customer"))
            {
                // accepts and ignores null-arguments
                customerService.loadTransientFieldsCurrentLenient(anEvent.getEntity().getCustomer());
            }
        }
    }
}