You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Richard Schurig <ri...@me.com> on 2011/01/22 10:42:43 UTC

IOC OSGi class loading issues

hi all,

we're using Tapestry IOC in an OSGi environment (Equinox 3.4) and recently discovered some serious class loading issues when installing multiple versions of the Tapestry Jars (5.1.0.5 and 5.2.4).

the problem itself lies in the class ClassFactoryClassPool, which picks up every class loader from every class it ever sees. this completely bypasses the OSGi way of class loading!

let me give an example: imagine 2 OSGi bundles names A and B as well as 2 Tapestry IOC bundles named T5.1 and T5.2. A is using imports from T5.1 and B is using imports from T5.2. but A is also using imports from B. an every day scenario in OSGi. now what happens: the IOC registry starting in bundle A is manipulating some class in its bundle, which has references to a class in B. this results in ClassFactoryClassPool picking up the class loader of the B-class (the bundle class loader of bundle B) and therefore seeing also all T5.2 classes. so you end up with two Tap versions in allLoaders, and it's just a matter of timing, if you have a working sequence in the chain.

the solution seems to be just using the thread context class loader, which (correctly set) provides all the classes needed by IOC. i did not understand the purpose the picking up class loaders anyway, is that a fix for tomcat/jetty? i tested the solution by patching (naahh) Tap IOC 5.1.0.5 ClassFactoryClassPool like that:

 public ClassFactoryClassPool(ClassLoader contextClassLoader)
    {
        super(null);

        ClassPath path = new LoaderClassPath(contextClassLoader);
        insertClassPath(path);
    }

 public synchronized void addClassLoaderIfNeeded(ClassLoader loader)
    {
        // Just do nothing
    }

This worked for me: in the first place a lot of "ClassNotFoundExceptions" occurred, revealing all the classes that we're accessible by bypassing the OSGi Bundle Class Loader, but after adding them to the imports of my bundle, everything was fine.

So now the question: is there a way to suppress this "picking up class loader" mechanism? maybe somehow replacing the ClassFactoryClassPool with a custom implementation without patching?

kind regards


Re: IOC OSGi class loading issues

Posted by Josh Canfield <jo...@gmail.com>.
Can you provide a tiny project that has the problem? OSGI deployments are
probably a little less common so the more code you provide the better.
On Jan 22, 2011 10:10 AM, "Richard Schurig" <ri...@me.com> wrote:
> hi all,
>
> we're using Tapestry IOC in an OSGi environment (Equinox 3.4) and
recently discovered some serious class loading issues when installing
multiple versions of the Tapestry Jars (5.1.0.5 and 5.2.4).
>
> the problem itself lies in the class ClassFactoryClassPool, which picks up
every class loader from every class it ever sees. this completely bypasses
the OSGi way of class loading!
>
> let me give an example: imagine 2 OSGi bundles names A and B as well as 2
Tapestry IOC bundles named T5.1 and T5.2. A is using imports from T5.1 and B
is using imports from T5.2. but A is also using imports from B. an every day
scenario in OSGi. now what happens: the IOC registry starting in bundle A is
manipulating some class in its bundle, which has references to a class in B.
this results in ClassFactoryClassPool picking up the class loader of the
B-class (the bundle class loader of bundle B) and therefore seeing also all
T5.2 classes. so you end up with two Tap versions in allLoaders, and it's
just a matter of timing, if you have a working sequence in the chain.
>
> the solution seems to be just using the thread context class loader, which
(correctly set) provides all the classes needed by IOC. i did not understand
the purpose the picking up class loaders anyway, is that a fix for
tomcat/jetty? i tested the solution by patching (naahh) Tap IOC 5.1.0.5
ClassFactoryClassPool like that:
>
> public ClassFactoryClassPool(ClassLoader contextClassLoader)
> {
> super(null);
>
> ClassPath path = new LoaderClassPath(contextClassLoader);
> insertClassPath(path);
> }
>
> public synchronized void addClassLoaderIfNeeded(ClassLoader loader)
> {
> // Just do nothing
> }
>
> This worked for me: in the first place a lot of "ClassNotFoundExceptions"
occurred, revealing all the classes that we're accessible by bypassing the
OSGi Bundle Class Loader, but after adding them to the imports of my bundle,
everything was fine.
>
> So now the question: is there a way to suppress this "picking up class
loader" mechanism? maybe somehow replacing the ClassFactoryClassPool with a
custom implementation without patching?
>
> kind regards
>