I have the same issue. After lot's of debugging I implemented a not-quick-but-dirty workaround. I don't use the real SessionFactoryImpl directly, but only through a dynamic proxy which overrides the #openSession() by #withOptions().tenantIdentifier(...).openSession(). Because SessionFactoryImpl is final, I wasn't override the method by subclassing. Additionally I had to implement the springs interface InfrastructureProxy and add an implementation for getWrappedObject(), because otherwise Springs SpringSessionContext wouldn't be able to find it's current session, opened by HibernateTransactionMonitor (using the proxy as key) and retrieved by SpringSessionContext (using the unproxied SessionFactoryImpl as key).
AOP wasn't a solution for this, because the final-modifier prevented subclassing by CGLIB (I'm not sure whether load-time-weaving were possible) and using dynamic proxies confused the SpringSessionContext.
In a first test it looks as it works fine (even if I'm not absolutely sure and would be happy to replace this hack by Hibernate 4.1.1). Does anybody know whether it'd be enough to override #openSession() with #withOptions().tenantIdentifier(...).openSession()?
Code:
public class CurrentTenantFixLocalSessionFactoryBean extends LocalSessionFactoryBean {
public class CurrentTenantIdentifierResolverFixWrapper implements
InvocationHandler {
private final String openSessionMethod="openSession";
private final String getWrappedObjectMethod="getWrappedObject";
private SessionFactoryImplementor factory;
public CurrentTenantIdentifierResolverFixWrapper(
SessionFactoryImplementor f) {
this.factory = f;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
CurrentTenantIdentifierResolver currentTenantIdentifierResolver = factory
.getCurrentTenantIdentifierResolver();
if (method.getName().equals(openSessionMethod) && method.getParameterTypes().length==0 && currentTenantIdentifierResolver != null) {
SessionBuilder sb = factory.withOptions();
String tenant = currentTenantIdentifierResolver.resolveCurrentTenantIdentifier();
sb.tenantIdentifier(tenant);
return sb.openSession();
} else if (method.getName().equals(getWrappedObjectMethod) && method.getParameterTypes().length==0) {
return factory;
} else {
return method.invoke(factory, args);
}
}
}
public SessionFactory getObject() {
SessionFactoryImplementor realFactory = (SessionFactoryImplementor) super
.getObject();
SessionFactoryImplementor proxiedFactory= (SessionFactoryImplementor) Proxy
.newProxyInstance(this.getClass().getClassLoader(),
new Class[] { SessionFactoryImplementor.class,
InfrastructureProxy.class },
new CurrentTenantIdentifierResolverFixWrapper(
realFactory));
return proxiedFactory;
}
}