db-jdo-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marco หงุ่ยตระกูล-Schulze <Ma...@NightLabs.de>
Subject Re: No joy with ClassLoaders
Date Thu, 08 Apr 2010 10:58:28 GMT
On 04/08/2010 05:09 AM, Michelle Caisse wrote:
> Thanks, Marco. I thought a custom class loader might be the answer.
> However, perhaps just my ignorance, but I don't see how to make that
> work given that the tests are launched via a maven goal, not directly
> from a java class under our control.
>
> -- Michelle
>

Hi Michelle,

looking at your patch
http://issues.apache.org/jira/secure/attachment/12439851/jdo-557.patch
it looks good but unfinished.

First, I'm not sure if your JDOConfigTestClassLoader filters out the
things you don't want to take over from the parent: The ordinary
contract of a class-loader is to first ask the parent and only if the
parent does not know the resource/class, look for it itself.

Second, you don't seem to do anything with this loader. You instantiate
it but you don't set it as thread-context-class-loader, thus if the
JDOHelper.getPersistenceManagerFactory() wants to obtain the
jdoconfig.xml (or other resources like properties files) from the
thread-context-class-loader, it will take the wrong class-loader.

If JDOHelper.getPersistenceManagerFactory() does not take the thread's
context-class-loader but the one with which the JDO-API was loaded, then
it takes the wrong class-loader, too, because JDO is already loaded before.

I'm sorry to say that I don't know exactly how
JDOHelper.getPersistenceManagerFactory() should behave, but if it is to
use the thread-context-class-loader then all you have to do is to add
sth. like this around:

ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(loader);
try {
  // Do what is currently done in the test method, i.e.
JDOHelper.getPersistenceManagerFactory()
} finally {
  Thread.currentThread().setContextClassLoader(oldCL);
}

If the JDOHelper uses the class-loader which was used to load the class
JDOHelper, then you have to use a separate helper class, which you
already load via your specific loader:

public class MyTestHelper {
  public void test() {
    // Do what you currently do in the test method, i.e. move
    // JDOHelper.getPersistenceManagerFactory() and the checks here.
  }
}

public class PMFMapMapTest
extends JDOHelperConfigTest implements Constants {

// ...

public void testJDOConfigXML() throws IOException {

    URLClassLoader loader = new JDOConfigTestClassLoader(
            JDOCONFIG_CLASSPATH_PREFIX,
            getClass().getClassLoader());
    ClasspathHelper.addFile(
            JDOCONFIG_CLASSPATH_PREFIX + "/Pmfmapmap01", loader);

    Class<?> c = loader.loadClass("mypackage.MyTestHelper");
    // instantiate and call the MyTestHelper.test() via reflection
}

// ...
}

This of course only works, if your JDOConfigTestClassLoader is
configured to override and reload the JDO-API (and *not* to use the
already loaded one from the parent).

I hope I could help.

Best regards, Marco :-)

Mime
View raw message