-----Original Message----- From: Stephen McConnell [mailto:[EMAIL PROTECTED] Sent: Thursday, January 01, 2004 3:53 PM
Olaf Bergner wrote:
-----Original Message----- From: Niclas Hedhman [mailto:[EMAIL PROTECTED] Sent: Wednesday, December 31, 2003 2:39 AM
I "wild" guess; The (Kernel) cast would then implicitly load the merlin-api jar, which probably then conflicts with the merlin-api being loaded by the avalon-repository system.
Probably something along those lines. Doubt that I will ever find out. I tried to follow your advice and traced all classloading events during the testcase. To that end I wrote a custom classloader which simply spat out which class was currently being loaded and if the effective
class loader was
the parent classloader or this classloader. This gave me a whole lot of info, albeit nothing useful. At least not for me. My faithful classloader was tracing and tracing and then, right out of the middle of
nowhere there
was this good ol' LinkageError again.
But then again, I had a look at the source for java.lang.ClassLoader and java.net.URLClassLoader. At least I learned a bit from this one.
Olaf:
Including container implementation jars in a project.xml will cause problems due to classloader logic in the JRE. The problem is that if an implementation class is included in the project.xml, then it going into a classloader constructed by maven. When you kernel or something like the AMTC kicks in the avalon-repository package is constructing a child classloader with the complete set of implementation resources - however, if an implementation class in merlin invokes an operation on another class, and if the other class is in the maven classloader, and the other class invokes an operation on a third class (which would normally be in the merlin classloader), it will not be found. This is because class lookup is always up relative to the classloader associated with the class making the invocation.
Makes sense. Thanks for that info. It's a little mind boggling at first sight but cannot possibly be harder than group theory. Still it's slippy ground.
The solution (that will let you get back to normal code and avoid reflection) is to declare a factory. So instead of using the repository package to load merlin you should use the repository package to load your own factory. The repository package will then create the classloader you need with everything in it and your dependencies in project.xml can be reduced down to nothing more than avalon-repository-main.
Thanks. I'll give it a try. Yet I think I'll have to get my head around some of the deeper merlin/repository mysteries first. Do I understand you correctly in that you are talking about replacing
Artifact artifact = DefaultBuilder.createImplementationArtifact( classloader, getMerlinHome(), getBaseDirectory(), MERLIN_PROPERTIES, IMPLEMENTATION_KEY);
The DefaultBuilder.createImplementationArtifact method is the important thing here. The IMPLEMENTATION_KEY argument in the above code is the classname of the Merlin kernel factory. Instead of using the Merlin DefaultFactory class (see merlin/kernel/impl package) you could supply your own factory (possible extending the Merlin factory).
String[] hosts = getHosts();
InitialContext context = new DefaultInitialContext(repository, hosts);
Builder builder = new DefaultBuilder(context, artifact); m_classloader = builder.getClassLoader();
The builder.getClassloader() operation returns a classloader containing the factory which means that you application specific code has all of the classes it needs. Take a look at DefaultFactory in kernel/impl and you will see that everything is available within the factory.
Factory factory = builder.getFactory();
where artifact represents a merlin kernel with some code so that artifact represents a merlin kernel *factory*? But as soon as I switch from using reflection in my testcase to the 'normal' way, e.g. as soon as I do something like
final Kernel meLovelyKernel = (Kernel) factory.create(criteria);
I'll be back to where I came from: maven's got to see the Kernel interface, and thus merlin-api's got to be in project.xml. Or did I get it all wrong?
Basically - put you kernel management logic down in the factory and use the testcase code to set and manipulate properties that are supplied to the builder when instantiating the kernel. Using this approach you can define new factory criteria arguments within your factory definition, populate the factory criteria with stuff relative to the context using the code in your testcase, then supply the criteria to the factory to create the kernel. The factory takes the criteria and based on that does whatever you want inside a classloader that is established by the repository (which includes all of the implementation classes nicely isolated away from the maven environment).
Please bear with me, but I definitely want to get this one straight since it's really been bothering me for quite a while.
No problem.
And now for something completely different: hope you and your's had a nice New Year's Eve. No misbegotten classloaders lurking on the bottom of some champagne bottle. All the best for a new year.
The new year came in with a bottle of Cuvee St-Vincent Grand Cru 1988 - nothing lurking there!
Cheers, Steve.
Cheers, Stephen.
Cheers,
Olaf
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
-- |------------------------------------------------| | Magic by Merlin | | Production by Avalon | | | | http://avalon.apache.org/merlin | | http://dpml.net/ | |------------------------------------------------|
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
