Hi,
as we experienced it is possible to hibernate and cglib jars live in another classloader as the POJO classes. However there seems to be a little bug causing the created proxy (the interfaces it implements) to live in the classloader loading hibernate instead of the classloader for the POJOs. CGLIB uses the classloader for the first passed interface as default. Hibernate passes the interfaces in an arbitrary order. One of the passed interfaces is the HibernateProxy interfaces loaded together with hibernate in one classloader. If - by accident - this interface is passed first the proxy interfaces live in the wrong namespace.
We solved this problem by patching the class:
org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory
(CGLIBProxyFactory.java 9210 2006-02-03 22:15:19Z steveebersole)
In this class we fond the code:
Code:
public void postInstantiate(
final String entityName,
final Class persistentClass,
final Set interfaces,
final Method getIdentifierMethod,
final Method setIdentifierMethod,
AbstractComponentType componentIdType)
throws HibernateException {
this.entityName = entityName;
this.persistentClass = persistentClass;
this.interfaces = (Class[]) interfaces.toArray(NO_CLASSES);
this.getIdentifierMethod = getIdentifierMethod;
this.setIdentifierMethod = setIdentifierMethod;
this.componentIdType = componentIdType;
factory = CGLIBLazyInitializer.getProxyFactory(persistentClass, this.interfaces);
}
Which we replaced with the following code:
Code:
public void postInstantiate(
final String entityName,
final Class persistentClass,
final Set interfaces,
final Method getIdentifierMethod,
final Method setIdentifierMethod,
AbstractComponentType componentIdType)
throws HibernateException {
this.entityName = entityName;
this.persistentClass = persistentClass;
this.interfaces = (Class[]) interfaces.toArray(NO_CLASSES);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if(this.interfaces.length > 1) {
Class firstIfc = this.interfaces[0];
if(firstIfc.getName().startsWith("org.hibernate")) {
this.interfaces[0] = this.interfaces[1];
this.interfaces[1] = firstIfc;
System.err.println("Replace: " + firstIfc.getName() + " by " + this.interfaces[0].getName());
}
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.getIdentifierMethod = getIdentifierMethod;
this.setIdentifierMethod = setIdentifierMethod;
this.componentIdType = componentIdType;
factory = CGLIBLazyInitializer.getProxyFactory(persistentClass, this.interfaces);
}
It would be of great interest if this is actually a bug in hibernate, and if it is planned to fix it....
Best regards,
Jan Wiemer
Code: