How to initialize and retrieve CustomEventListeners in Hibernate 4.x and 5.x


#1

Hi everyone,
I’m migrating a tool from Hibernate 3.2 to the latest release, but also 4.3.10. In the original tool, the EventListeners were initialized in Configuration. However, this seems to have changed from 4.x and onward.

The way the tool works originally is that it would call initialize in the constructor from this subclass of Configuration to set up the Load and CollectionInitializationEventListeners. Can I still set up the listeners from this class? I’ve been playing around with EventListenerRegistry, but I how would I retrieve the instance? I’ve tried the following way retrieve it, but it’s dependent on having an instance of a SessionFactory, which from my understanding I don’t have at this point.

final EventListenerRegistry registry = ((SessionFactoryImpl) getSessionFactoryObserver().)
                .getServiceRegistry().getService(EventListenerRegistry.class);

The relevant code is displayed here:

public class AutofetchConfiguration extends Configuration {
...
...
...
...
private void initialize() {
        extentManager = new ExtentManager();
        getEventListeners().setLoadEventListeners(new LoadEventListener[] {
            new AutofetchLoadListener(extentManager) });
        getEventListeners().setInitializeCollectionEventListeners(
                new InitializeCollectionEventListener[] { 
                        new AutofetchInitializeCollectionListener(
                                extentManager) });
        setInterceptor(new AutofetchInterceptor(EmptyInterceptor.INSTANCE,
                extentManager));
    }

    /**
     * Ensures that any interceptor is wrapped with the AutofetchInterceptor.
     */
    @Override
    public Configuration setInterceptor(Interceptor i) {
        if (i instanceof AutofetchInterceptor) {
            return super.setInterceptor(i);
        } else {
            AutofetchInterceptor ai = (AutofetchInterceptor) getInterceptor();
            return super.setInterceptor(ai.copy(i));
        }
    }
    
    /**
     * Ensures that the extent manager is set for any Autofetch
     * listeners.
     */
    @Override
    public void setListeners(String type, Object[] listeners) {
        setExtentManager(listeners, extentManager);
        super.setListeners(type, listeners);
    }
    
    public ExtentManager getExtentManager() {
        return extentManager;
    }

    public void setExtentManager(ExtentManager em) {
        this.extentManager = em;
        // Propagate changes to listeners and interceptor
        AutofetchInterceptor ai = (AutofetchInterceptor) getInterceptor();
        ai.setExtentManager(em);
        setExtentManager(
                getEventListeners().getInitializeCollectionEventListeners(),
                em);
        setExtentManager(
                getEventListeners().getLoadEventListeners(),
                em);
    }
    
    private void setExtentManager(Object[] listeners, ExtentManager em) {
        for (Object listener : listeners) {
            if (listener instanceof AutofetchInitializeCollectionListener) {
                ((AutofetchInitializeCollectionListener)listener).setExtentManager(em);
            }
            if (listener instanceof AutofetchLoadListener) {
                ((AutofetchLoadListener)listener).setExtentManager(em);
            }
        }
    }
}

From what I’ve read you can set:

		registry.setListeners(EventType.LOAD, new AutofetchLoadListener());
		registry.setListeners(EventType.INIT_COLLECTION, new AutofetchInitializeCollectionListener(extentManager));

But how do I retrieve the instance of the EventListenerRegistry? Also, the overridden method setListeners does not exist in Configuration anymore so I would need to find another method to override to make sure that the Autofetch listeners have an ExtentManager set for them.

Any type of input is appreciated. Thanks in advance.


#2

There are multiple ways to provide EntityListeners. Check out this User Guide chapter in Hibernate 5.2.

  1. You can use a org.hibernate.integrator.spi.Integrator and provide that via the SessionFactoryBuilder
  2. You can provide them via the EventListenerRegistry.

You will find lots of details in the Bootstrap chapter as well.

Although the doc is for 5.2, it might be relevant to 4.x as well. The 4.x branch does not have an up-to-date documentation since we took care of rewriting the docs in Hibernate 5.


#3

Thanks for the answer, the links that you have provided will be very useful in the development.