1

I'm using Spring Boot v2.0.3 with Hibernate 5.2. I would like to create an Hibernate Interceptor to generate a value in one of my entity field, based on a unique number in my database, before it got saved.

I fetched some online ressources, and ended up extending the Hibernate EmptyInterceptor to just override the onSave method.

@Component
public class CustomInterceptor extends EmptyInterceptor {

    private final TicketService ticketService;

    @Autowired
    public CustomInterceptor(TicketService ticketService) {
        this.ticketService = ticketService;
    }

    public boolean onSave(Object entity,
                       Serializable id,
                       Object[] state,
                       String[] propertyNames,
                       Type[] types) {

        if (entity instanceof Ticket) {
            if (((Ticket) entity).getNumTicket() == null) {
                String pharmacyId = ((Ticket) entity).getEtablishmentId();

                Long newTicketNumber = ticketService.findMaxNumTicketForEtablishment(etablishmentId);
                // ((Ticket) entity).setNumTicket((newTicketNumber != null ? newTicketNumber : 1));
                for ( int i = 0; i < propertyNames.length; i++ ) {
                    if ( "numTicket".equals( propertyNames[i] ) ) {
                        state[i] = newTicketNumber;
                        return true;
                    }
                }
                return true;
            }
        }
        return false;
    }
}

In my application.yml config file, I added the following key :

spring.jpa.properties.hibernate.ejb.interceptor: com.mycompany.xxx.utils.CustomInterceptor

When I try a Ticket saving, I can see that the method onSave is correctly called, but as the interceptor was instantiated purely by Hibernate, it's not in the Spring bean context, so I can't use the @Autowire annotation. (so my ticketService is null).

In a old subject ( How to use Spring managed Hibernate interceptors in Spring Boot?), I see that someone tried to override the HibernateJpaAutoConfiguration vendor properties, but it's not available anymore.

I found this issue on Github : https://github.com/spring-projects/spring-boot/issues/11211 , perfectly illustrating my problem, but I couldn't successfully make it work (tried to create an HibernatePropertieCustomizer as well, but I failed to use it).

if anyone can point me out to the right direction, I would be grateful. thanks

Alex
  • 4,599
  • 4
  • 22
  • 42

1 Answers1

1

I found this issue on Github : https://github.com/spring-projects/spring-boot/issues/11211 , perfectly illustrating my problem,

I am not sure how #11211 is related at all since you are reporting a problem trying to use dependency injection in a component that is managed by Hibernate.

First thing first, you are registering a class (not a bean) to Hibernate so adding @Component is not a great idea as Hibernate is now responsible to instantiate your class. If you add @Component it looks like you expect component scanning to handle this object (while, in fact, Hibernate will process it based on the FQN you've provided in configuration).

Then, Hibernate has added a way to customize how such instantiation happens and Spring Boot auto-configures a SpringBeanContainer by default as of #13717 which is available in Spring Boot 2.1.x only. If you want to be able to use regular dependency injection, you need to upgrade to Spring Boot 2.1.

Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
  • In the original post of the issue, RizziCR wrote "It's possible to add the interceptor as property "spring.jpa.properties.hibernate.session_factory.interceptor", but this is a hibernate instance and not accessible in the spring context.". That's basically what I describe as my problem in this post. Anyway, thanks for the answer, I'll have to upgrade Spring as soon as possible. – Alex Dec 20 '18 at 10:50