[hibernate-issues] [Hibernate-JIRA] Commented: (HHH-1131) setting classloader in CGLIB class generators

Bart den Haak (JIRA) noreply at atlassian.com
Mon Sep 3 08:46:14 EDT 2007


    [ http://opensource.atlassian.com/projects/hibernate/browse/HHH-1131?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_28001 ] 

Bart den Haak commented on HHH-1131:
------------------------------------

This fix really works for me too! I'm using OSGi technolgy (dynamic loading) and with this fix it will work. This without putting the default-lazy='false' attribute on my <hibernate-mapping> element. Also very handy when using HyperJAXB3 (with hibernate annotations).

This is my fix for hibernate core 3.2.1GA. Just replace the CGLIBLazyInitializer.getProxyFactory() method in the the package org/hibernate/proxy/pojo/cglib/CGLIBLazyInitializer.java (see SVN http://anonsvn.jboss.org/repos) by this one. You could compile this class by yourself (with hibernate core in your classpath) and override the class file in the hibernate-3.2.1GA.jar. 

public static Class getProxyFactory(Class persistentClass, Class[] interfaces)
			throws HibernateException {
		Enhancer e = new Enhancer();
		e.setSuperclass( interfaces.length == 1 ? persistentClass : null );
		e.setInterfaces(interfaces);
		e.setCallbackTypes(new Class[]{
			InvocationHandler.class,
			NoOp.class,
	  		});
  		e.setCallbackFilter(FINALIZE_FILTER);
  		e.setUseFactory(false);
		e.setInterceptDuringConstruction( false );
		
		ClassLoader classLoader = null;
		
		// -- -FIX STARTS HERE ---
		try {
		    classLoader = Class.forName("org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer").getClassLoader();
		}
		catch (ClassNotFoundException e1) {
		    e1.printStackTrace();
		}
		
		if(classLoader == null){
		    e.setClassLoader(Thread.currentThread().getContextClassLoader());
		    System.out.println("--> USING currentThread classloader");
		}
		else{
		    e.setClassLoader( classLoader );
		    System.out.println("--> USING org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer classloader");
		}		
   
                // --- FIX END ---
		
		return e.createClass();
	}





> setting classloader in CGLIB class generators
> ---------------------------------------------
>
>                 Key: HHH-1131
>                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1131
>             Project: Hibernate3
>          Issue Type: Improvement
>          Components: core
>    Affects Versions: 3.0.5
>         Environment: Hibernate 3.0.5, Oracle 10
>            Reporter: Moshe Ben Shoham
>
> In my application I am loading plug-ins mapping documents and persistent classes from jars using some UrlClassLoaders (one per plugin). I then set the threadContextClassLoader to be the CompositeClassLoader that holds all those UrlClassLoaders. Everything works fine until I add a proxy to one of the mapping document (I simplified the names a little): 
> <hibernate-mapping> 
>    <subclass 
>       name="myplugin.MyExtension" 
>       discriminator-value="3" 
>       proxy="myplugin.IMyExtension"
>       extends="core.MyBasicClass" 
>    > 
>       <join table="MY_EXTENSION"> 
>               <key column="ENTITY_ID"/> 
>           <property name="extraNumData" column="EXTRA_NUM_DATA" type="long"/> 
>           <property name="extraStrData" column="EXTRA_STR_DATA" type="string"/> 
>       </join> 
>    </subclass > 
> </hibernate-mapping> 
> See below the exception I get. 
> Hibernate uses net.sf.cglib.proxy.Enhancer as the class generator in CGLIBLazyInitializer.getProxyFactory(). Now, it seeme like CGLIB allows customizing the ClassLoader used by its class generators using the method net.sf.cglib.core.AbstractClassGenerator.setClassLoader() (Enhancer extends AbstractClassGenerator). But, it doesn't seem like it is possible to use it in Hibernate, because this is how the Enhancer is used in CGLIBLazyInitializer.getProxyFactory() : 
> return (Factory) Enhancer.create( 
>   (interfaces.length==1) ? persistentClass : null, 
>   interfaces, 
>   NULL_METHOD_INTERCEPTOR 
> ); 
> If I replace it with the following code, it works: 
> Enhancer e = new Enhancer(); 
> e.setSuperclass((interfaces.length==1) ? persistentClass : null); 
> e.setInterfaces(interfaces); 
> e.setCallback(NULL_METHOD_INTERCEPTOR); 
> e.setClassLoader(Thread.currentThread().getContextClassLoader()); // this is the addition! 
> return (Factory)e.create(); 
> Is there any other way I can do it (I know I can implement my own persister, but it seems like there's too much code that needs to be overridden...)? 
> Is there any planned enhancement regarding this issue?
> Full stack trace of any exception that occurs: 
> CGLIB Enhancement failed: com.octavian.fas.domain.business.BusinessTransaction 
> net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null 
> at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:236) 
> at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:373) 
> at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:281) 
> at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:640) 
> at org.hibernate.proxy.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:94) 
> at org.hibernate.proxy.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:42) 
> at org.hibernate.tuple.PojoTuplizer.buildProxyFactory(PojoTuplizer.java:144) 
> at org.hibernate.tuple.AbstractTuplizer.<init>(AbstractTuplizer.java:83) 
> at org.hibernate.tuple.PojoTuplizer.<init>(PojoTuplizer.java:54) 
> at org.hibernate.tuple.TuplizerLookup.create(TuplizerLookup.java:47) 
> at org.hibernate.tuple.EntityMetamodel.<init>(EntityMetamodel.java:218) 
> at org.hibernate.persister.entity.BasicEntityPersister.<init>(BasicEntityPersister.java:400) 
> at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:104) 
> at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:55) 
> at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:211) 
> at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1005) 
> at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:777) 
> at org.springframework.orm.hibernate3.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:703) 
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1058) 
> at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:363) 
> at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:226) 
> at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:147) 
> at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:269) 
> at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:318) 
> at com.octavian.sma.analytical.batch.SpringHelper.init(SpringHelper.java:77) 
> at com.octavian.sma.analytical.batch.SpringHelper.<init>(SpringHelper.java:38) 
> at com.octavian.sma.analytical.batch.dailynongrouping.DailyNonGroupingAnalyticalBatch.initSpringHelper(DailyNonGroupingAnalyticalBatch.java:44) 
> at com.octavian.sma.analytical.batch.AnalyticalBatch.run(AnalyticalBatch.java:58) 
> at com.octavian.sma.analytical.batch.dailynongrouping.DailyNonGroupingAnalyticalBatch.main(DailyNonGroupingAnalyticalBatch.java:29) 
> Caused by: java.lang.reflect.InvocationTargetException 
> at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source) 
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
> at java.lang.reflect.Method.invoke(Method.java:585) 
> at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:373) 
> at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:218) 
> ... 28 more 
> Caused by: java.lang.NoClassDefFoundError: myplugin/IMyBusinessTransactionExtension 
> at java.lang.ClassLoader.defineClass1(Native Method) 
> at java.lang.ClassLoader.defineClass(ClassLoader.java:620) 
> ... 33 more

-- 
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