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]