c_inconnu3 wrote:

Joakim Erdfelt a écrit :

Thanks for this great help, i was going mad... :-)

This works :
* this.getClass().getClassLoader().getResourceAsStream("a/b/c/myTest.properties");

This DOES NOT works :
* ClassLoader.getSystemResourceAsStream("a/b/c/myTest.properties");
* this.getClass().getClassLoader().getSystemResourceAsStream("a/b/c/myTest.properties");

<quote>
If that works, I'll explain why. ;-)
</quote>

Jason has far more experience with Custom ClassLoaders than I do, but this is what I've learned ...

ClassLoaders are a way for the JVM to load a resource, the most traditional techniques being from a file system or from a jar file, and the most common resource being the raw bytes of a class file.

The call to ClassLoader.getSystemResourceAsString() will use the System ClassLoader, which is top level ClassLoader that gets populated with the classpath from the java command line, the CLASSPATH environment variable, and the contents of the extension folder. (Man, I'm really over-simplifying things here, there's more subtly then this when you get into the guts of it, but I don't think that's important for this explanation).

Maven manages what dependencies the Plugins and Projects can see by using a custom ClassLoader.

A custom ClassLoader, that is placed into the Thread.setContextClassLoader(), can isolate the dependencies required to exist only for the processes running within the life of that thread.

This is how the Maven Container (and J2EE Containers) can have multiple programs using incompatible dependencies operate with complete oblivion to each other.

In your example, you are actually running within 2 isolations of ClassLoaders.

     1) System ClassLoader (which maven core runs in)
   1.1) Plugin Isolated ClassLoader (which maven core spawned)
 1.1.1) Surefire Battery ClassLoader (which the surefire spawned)
1.1.1.a) Your tests.

When your original code running in the nested ClassLoader at 1.1.1.a asked the default System ClassLoader to obtain a resource, you essentially asked for a resource in the classpath all the way up at step 1.

When you changed your test to use this.getClass().getClassLoader().getResource... you stated that you want to use the same ClassLoader that started the tests. (which would be the one at 1.1.1).

That's why it worked.

BTW: I've gotten into the habit of always using the ClassLoader from the loaded class, this makes my libraries work everywhere.

Here's a snippet of code that I use to bootstrap a ClassLoader and kick of the 'public void main(String args[])' method in another class.

 URLClassLoader loader = new URLClassLoader(locator.getUrls());
 Thread.currentThread().setContextClassLoader(loader);
 Class mainClass = loader.loadClass("com.initech.vi.rus.Cli");
 Object objmain = mainClass.newInstance();
 Class argClass = Array.newInstance(String.class, 0).getClass();
 Method mainMethod = mainClass.getMethod("main", new Class[] { argClass });
 String arguments[] = (String[]) argList.toArray(new String[0]);
 mainMethod.invoke(objmain, new Object[] { arguments });

Hope that fulfills my promise. ;-)

/* Joakim Erdfelt */

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to