I have a Spring Framework 4 application that uses Hibernate 4.3.8 as the JPA provider. I want to use Hibernate filters, and therefore I need to enable them. I want to do this globally in the application, which I am trying to do with Spring AOP. The idea is that I can write an aspect that enables filters every time a session is created/fetched, like in this and this question.
I have added the spring-aop
and aspectjweaver
dependencies to my project (using Maven). I have added the following aspect.
@Aspect
@Component
public class EnableHibernateFilters {
@Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")
protected void sessionBeingFetched() {
}
@AfterReturning(pointcut = "sessionBeingFetched()", returning = "object")
public void enableFilters(JoinPoint joinPoint, Object object) {
System.out.println("!!! Enabling filters !!!"); // Never printed
Session session = (Session) object;
session.enableFilter("myFilter");
}
}
My problem is that the above advice (enableFilters
) is never invoked; neither the text is printed, nor is my filter enabled. I have verified that my aspect is detected and that AOP works in my project by changing the pointcut to one of my own classes. I have also tried to change the pointcut to execution(* org.hibernate.SessionFactory.openSession(..))
, but with no result.
I suspect that this is caused by how I set up Hibernate, because I don't configure a SessionFactory
explicitly; rather, I set up an EntityManagerFactory
. Here is my configuration.
@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public DataSource dataSource() throws NamingException {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/postgres"); // JNDI lookup
}
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException, NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(...);
factory.setDataSource(this.dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JpaTransactionManager transactionManager() throws SQLException, NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(this.entityManagerFactory());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
Basically I am not sure which pointcut to use with the above configuration. I have tried to mess around with LocalContainerEntityManagerFactoryBean.setLoadTimeWeaver()
, but I couldn't figure it out. I don't know if I even need to configure that anyways.
Essentially, my AOP setup works for my own custom classes. I guess either the problem is that weaving is not configured with Hibernate or something (I am very unfamiliar with this part of it all) or that the session is not obtained through the SessionFactory.getCurrentSession()
method due to my setup. I tried to verify that my advice even worked with Hibernate by changing my pointcut to execution(* org.hibernate.Hibernate.isInitialized(..))
and manually invoking Hibernate.isInitialized(null)
in my code, but this did not trigger the advice either, so this might be the problem. I tried what was suggested in this post to enable Hibernate weaving, but I couldn't get it to make any difference.
I also tried to set my pointcut to execution(* org.springframework.orm.hibernate4.SessionHolder.getSession(..))
and execution(* org.springframework.orm.jpa.vendor.HibernateJpaDialect.getSession(..))
, but also without any luck.
So, I am not sure where to go next. How can I get a hold of Hibernate's Session
object from my advice such that I can enable Hibernate filters? Thank you in advance!
EDIT:
Just in case, I do have @EnableAspectJAutoProxy
present in my configuration:
@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
// ...
}