You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Benjamin Renaud <be...@gmail.com> on 2008/11/01 00:23:07 UTC

createInstance calls Class.forName - unexpected behavior


Hi,

I've recently started developing an app using OpenJPA, and this is  
what I am doing:

1. Let the user specify some arbitrary data (essentially classes with  
fields)

2. Take that metadata and turn it into synthetic java interfaces, with  
annotations.

3. Build a specific EMF that targets a specific Postgresql schema

4. Set my own ClassResolver on the EMF,

5. The ClassResolver returns a custom classloader which knows how to  
make and load these synthetic interfaces, and runs calls the MetaData  
facility on the class to create the OpenJPA MetaData.

6. Set the ContextClassLoader to my classloader. Get an EM from the  
EMF, and call createInstance(syntheticClass) in the hope of coming up  
with an entity I can persist and use.

This is where I am running into trouble.

I have determined that everything looks reasonable up until the point  
where the OpenJPA runtime tried to instantiate the instance, in  
org.apache.openjpa.meta.InterfaceImplGenerator.createImpl.

The following code snippet is where I hit a snag:

         try {
             meta.setInterfaceImpl(Class.forName(bc.getName(), true,  
loader));
         } catch (Throwable t) {
             throw new InternalException(_loc.get("interface-load",  
iface,
                 loader), t).setFatal(true);
         }

(line 109 in my 1.2.0 source)

Debugging tells me that

- the SERP classloaders being used in this context (both the enhancer  
and the regular loader, 'loader' in the snippet above) both have my  
classloader as their parent (good).
- they also are both attached to a SERP project which -knows- about  
the implementation class in question (in its names variable - which  
therefore means that BCClassLoaders with it as their parent should be  
able to load it), named something like my_package.my_interface 
$myinterfaceopenjpaimpl

yet it basically can't find it.

It would appear that Class.forName in the snippet above ends up  
calling findClass() in my classLoader but NOT findClass() in 'loader'   
which ends up causing a ClassNotFoundException.

I can't explain why Class.forName doesn't do the right thing (it's  
really a native method and the javadocs are a little vague), but I am  
curious as to why the code snippet above doesn't simply call  
loader.loadClass(bc.getName())?

Any insight into this issue would be much appreciated. (Including if I  
am doing something unexpected)

Thank you,
Benjamin