Search code examples
springspring-boothibernatespring-aop

How to enable hibernate filter using AOP and Spring Boot?


I am trying to enable an hibernate filter using Spring AOP And Spring Boot. I used this post as a starter point:How to enable hibernate filter for sessionFactory.getCurrentSession()?

So far I haven't been able to intercept the Hibernate session:org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl.openSession().

My aspect class looks like this:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import com.acme.CustomUserDetails;

@Component
@Aspect
public class ACLFilter {
    Logger log = LoggerFactory.getLogger(ACLFilter.class);

    @AfterReturning(pointcut = "execution(* org.hibernate.internal.SessionFactoryImpl.openSession(..)))", returning = "session")
    public void forceFilter(JoinPoint joinPoint, Object session) {
        Session hibernateSession = (Session) session;
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Long userId = ((CustomUserDetails) auth.getDetails()).getUserId();
        // Session session = em.unwrap(Session.class);
        hibernateSession.enableFilter("groupACL").setParameter("userId", userId);
    }

    @Before("execution(* org.hibernate.SessionFactory.openSession(..)))")
    public void do2(JoinPoint joinPoint) {
        System.out.println("############################do2");
    }

    @Before("execution(* org.hibernate.SessionBuilder.openSession(..)))")
    public void do3(JoinPoint joinPoint) {
        System.out.println("############################do3");
    }

    @Before("execution(* org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl.openSession(..)))")
    public void do4(JoinPoint joinPoint) {
        System.out.println("############################do4");
    }

}

This is all the classes/methods I tried to intercept. I also validated that the aspect class was working correctly with a test class/method and it does, so the AOP setup is correct. While debugging I can see that the system triggers org.hibernate.internal.SessionFactoryImpl.SessionBuilderImpl.openSession() but doesn't trigger my interceptor? My application.properties file include this entry:

spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext

What am I missing?


Solution

  • The Hibernate classes are not Spring components, thus Spring AOP does not work for them. If you want to intercept them, I suggest you switch to full AspectJ with load-time weaving. Then you also have a choice not to use execution() which would manipulate Hibernate's bytecode, but call() instead which would only change your own classes.