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
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.