> From: Shash Chatterjee [mailto:shash_list@;hotmail.com]
>
> Berin,
>
> Given what you say, here's what I'll try. Let me know what you think.
> The issue is that, particularly when the Fortress-based
> container will be
> run within a webapp, we were trying to avoid conflicts with
> the versions of
> JARs (Xerces is a good example) that the Webapp in general,
> or even the
> servlet-container, needs versus the one needed for the
> container/server we
> are working on. But I think I can simply set the
> contextClassLoader of a
> Thread, before any of the Avalon/Excalibur classes have been
> instantiated
> and then from that thread use ContextBuilder to create our container.
That is one of the solutions. Another solution is to use a
Servlet container that complies with Servlet 2.4 specifications.
Those mandate that the servlet classloader is isolated from the
server classloader. One example of a compliant container is
Tomcat 4.
> In general, I'm sure this is not an isolated problem for us?
> What is the
> design pattern to use with Fortress when the parent classloader could
> potentially have an incompatible version of a particular lib?
So far, the solution was to separate the classloaders and have
the new classloader load the correct versions of the classes.
> I think I understand the core problem I was having, but let
> me regurgitate
> so you can tell me right or wrong. The problem is not really
> with the
> instance of ThreadSafeCompinentHandler.class that my
> class-loader just
> loaded, but the parameter type instances in the constructor
> are loaded by
> the child loader while those being compared by
> getConstructor() are from the
> parent class-loader. If that's true, then I think I understand!
Not quite--but you are on the right track. Your classloader
defeated the parent classloader mechanism of the URLClassLoader
object. Fortress uses the supplied classloader to load all
classes that it creates. As a result, we had something like
this:
ParentClassLoader:
Had all Avalon stuff
SpecialClassLoader:
Had your components
When Fortress tried to use the SpecialClassLoader to load
Avalon stuff, it either did not find the class, or it loaded
a new copy of the class. Fortress searched the class for
a constructor that matched the set of parameters in the
ComponentHandler interface.
The problem arose because of one fundamental problem with
classloaders:
java.lang.String.class from ClassLoader A
!=
java.lang.String.class from ClassLoader B
To illustrate this point, use a URLClassLoader without any
parent (it will by default use the SystemClassLoader as a
parent) to load an external JAR. Instantiate another to
load the same JAR. Load the same class from both
classloaders, and then compare them with the equals() method.
They are not equal!
public void testClassEquality() throws Exception
{
ClassLoader a =
new URLClassLoader(
new URL[] { new File("sample.jar").toURL() } );
ClassLoader b =
new URLClassLoader(
new URL[] { new File("sample.jar").toURL() } );
Class aClass = a.loadClass( "sample.SomeObject" );
Class bClass = b.loadClass( "sample.SomeObject" );
if ( aClass.equals( bClass ) )
{
System.out.println(
"Berin is wrong and don't listen to him again" );
}
else
{
System.out.println(
"Berin is right, but he learned from smarter people" );
}
}
You should see a message proving that I am right, as long as
there is a file called "sample.jar" with a sample.SomeObject
class in there.
When you remove the hierarchical nature that is part of the
classloader definition, then you don't even have the
SystemClassLoader available to you.
--
To unsubscribe, e-mail: <mailto:avalon-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@;jakarta.apache.org>