spring-boothibernate

Hibernate integrator - Unknown service org.hibernate.event.service.spi.EventListenerRegistry


Hibernate 6.6.1.Final, Spring boot 3.3.4

I try to add event listeners to my project but I'm getting this exception when I start the application:

Caused by: org.hibernate.service.UnknownServiceException: Unknown service requested [org.hibernate.event.service.spi.EventListenerRegistry] 
at fr.sofia.sad.service.config.EventListenerIntegrator.integrate(EventListenerIntegrator.java:16)

Here is my configuration:

public class EventListenerIntegrator implements Integrator {

    @Override
    public void integrate(Metadata metadata, BootstrapContext bootstrapContext, SessionFactoryImplementor sessionFactory) {
        final EventListenerRegistry eventListenerRegistry = bootstrapContext.getServiceRegistry()
                                                                            .getService(EventListenerRegistry.class);
        eventListenerRegistry.appendListeners(EventType.POST_COMMIT_INSERT, PostInsertUpdateEventListener.class);
        eventListenerRegistry.appendListeners(EventType.POST_COMMIT_UPDATE, PostInsertUpdateEventListener.class);
    }

    @Override
    public void disintegrate(final SessionFactoryImplementor sessionFactory, final SessionFactoryServiceRegistry serviceRegistry) {
        //empty
    }
}

If I reference my integrator directly spring is telling me that there is a cast exception because my integrator is not a org.hibernate.jpa.boot.spi.IntegratorProvider so that's how I register it in my application.yml:

spring.jpa.properties.hibernate.integrator_provider: config.HibernateIntegratorProvider

With

import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.boot.spi.IntegratorProvider;

public class HibernateIntegratorProvider implements IntegratorProvider {

    @Override
    public List<Integrator> getIntegrators() {
        return List.of(new EventListenerIntegrator());
    }
}

I dont understand why the service is unknown and that's the way hibernate documentation recommend for creating the integrator: https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#bootstrap-event-listener-registration


Solution

  • If you want to add an event listener to your application, you must implement its interface. In Hibernate, each event has its own interface, there are quite a few of them, you can find these interfaces in the org.hibernate.event.spi package. Let's say you need to track the loading of objects, then you need the LoadEventListener interface:

    public class CustomEventListener implements LoadEventListener {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(CustomEventListener.class);
    
        @Override
        public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException {
            LOGGER.info("load event");
        }
    }
    
    

    In order for your listener to be able to respond to events, he must be registered in the listener registry:

    @Configuration
    public class HibernateListenerConfig {
    
        @Autowired
        private EntityManagerFactory entityManagerFactory;
    
        @PostConstruct
        public void registerHibernateEventListeners() {
            SessionFactoryImplementor sessionFactory = entityManagerFactory.unwrap(SessionFactoryImplementor.class );
            sessionFactory
                    .getServiceRegistry()
                    .getService( EventListenerRegistry.class )
                    .prependListeners(EventType.LOAD, new CustomEventListener());
        }
    }
    

    For more information, see сhapter 15.2 of the Hibernate ORM User Guide.