[hibernate-issues] [Hibernate-JIRA] Created: (HHH-5962) Custom POJO Loading strategy for cglib and javassist

Ilya Samartsev (JIRA) noreply at atlassian.com
Fri Feb 25 07:16:08 EST 2011


Custom POJO Loading strategy for cglib and javassist
----------------------------------------------------

                 Key: HHH-5962
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5962
             Project: Hibernate Core
          Issue Type: Bug
          Components: core
    Affects Versions: 3.6.1
         Environment: Hibernate 3.6.1, PostgreSQL, OSGi
            Reporter: Ilya Samartsev


I use hibernate in OSGi-enabled environment and have found a strange class-loading behaviour of the initializer proxies. The problem is that it's not possible to define simple domain-model OSGi bundles which have pojo-based classes to be enhanced by hibernate without importing org.hibernate.*, net.sf.cglib.proxy.*, javassist.util.proxy.*, etc.

Testing environment:
 - A Model bundle with pojos and hibernate HBMs(they used by osgi-hibernate loader to enhance them). This bundle doesn't actually require any hibernate/cglib/javassist imports for the reason there are simple pojos in it.
  /src/com/example/TestPojoModel.java
  /META-INF/mappings/TestPojoModel.hbm.xml
  /META-INF/MANIFEST.MF

Expected behaviour:
To have "clean" bundle with pojos without any additional imports(e.g. org.hibernate.* or cglib/javassist).
Enhance these classes without any errors.

Current behaviour:
These pojo-based model bundles require to import a lot of hibernate and cglib or javassist stuff to enhance these pojos. The problem is that hibernate uses the same classloader (from model bundle) to load both pojos and hibernate/codegeneration utility classes. Otherwise it crushes with ClassNotFoundException.

Code explanation:
Javassist ProxyFactory initialization:
 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer:
    ProxyFactory factory = new ProxyFactory();
    factory.setSuperclass( interfaces.length == 1 ? persistentClass : null );
    factory.setInterfaces( interfaces );
    factory.setFilter( FINALIZE_FILTER );
    return factory.createClass();

How javassist loads classes by default:
 javassist.util.proxy.ProxyFactory:
    protected ClassLoader getClassLoader0() {
      ClassLoader loader = null;
      if (superClass != null && !superClass.getName().equals("java.lang.Object"))
        loader = superClass.getClassLoader();
      else if (interfaces != null && interfaces.length > 0)
        ...
      }
      return loader;
}
It actually uses the classloader of the persistent class. 

My proposition:
To create advanced classloader for ProxyFactory which has custom behaviour:
1. Firstly it tries to load class using the classloader of the persistent class
2. Secondly it tries to use the classloader of the curent hibernate bundle (which definitely has access to its own hibernate classes and imports the classes of the codegeneration libraries)

final ClassLoader platformDelegatingClassLoader = new ClassLoader(persistentClass.getClassLoader()) {
  private final ClassLoader platformClassLoader = getClass().getClassLoader();

  // on loadClass() it tries to use parent's classloader(parent = persistentClass.getClassLoader() - from the constructor)
  // if loadClass() didn't find class it tries to findClass() which is actually overridden to use current context's getClass().getClassLoader()

  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
    return platformClassLoader.loadClass(name);
  }
};

ProxyFactory factory = new ProxyFactory() {
  @Override
  protected ClassLoader getClassLoader() {
    return platformDelegatingClassLoader;
  }
};


-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list