Well if osgi needs a different classloader which at some stages is not
the context classloader the current classloader then yes
this would help.
Werner
Bruno Aranda schrieb:
I agree if I understand it correctly. This would help as well to deal
with the classloading stuff for OSGi,
Cheers,
Bruno
2009/8/14 Werner Punz <[email protected]>:
Hia, while I am still preparing my groovy stuff I digged through
the myfaces class loading code.
Here is my problem, I currently use a custom classloader which roots into
the groovy code and if a file is present loads the class dynamically if not
it loads the class via the classloader currently set.
This mechanism is needed to be able to load the groovy artefacts from
various parts of jsf like view handlers, managed beans etc...
However this is messy, adding a classloader to a webapp is a no go.
I noticed that due to an issue regarding webapp startups (ear containers
change classloaders on the fly so you cannot rely on the context classloader
alone) all the forName code already has a centralized loading location in
place for artefacts.
To be able to deal with this problem in a clean way I would propose
following.
We should change the pattern of the classloading code to a chain of
responsibility pattern which means instead of:
public static Class classForName(String type)
throws ClassNotFoundException
{
if (type == null) throw new NullPointerException("type");
try
{
// Try WebApp ClassLoader first
return Class.forName(type,
false, // do not initialize for faster
startup
getContextClassLoader());
}
catch (ClassNotFoundException ignore)
{
// fallback: Try ClassLoader for ClassUtils (i.e. the myfaces.jar
lib)
return Class.forName(type,
false, // do not initialize for faster
startup
ClassUtils.class.getClassLoader());
}
}
we should do it the following way
public static Class classForName(String type)
throws ClassNotFoundException
{
if (type == null) throw new NullPointerException("type");
for(ClassLoaderExtension extension: classLoadingExtensions) {
Class retVal = extension.forName(type);
if(retVal != null) {
return retVal;
}
}
throw new ClassNotFoundException(name);
}
The main issue is all the existing methods are static so we
have to add the datastructures as well in a static way
(and probably we wont need a thread safety as well so we can
get a better performance for not doing it synchronized)
With the core logic of forName being distributed over several chain objects
And if we have a lot of those forName calls we might have a small
probably neglectable performance impact (might be fixable if we go
from arraylists to real arrays which are on assembler level cause
less operations).
This method would enable to plug in other loading mechanisms without
having to change the context classloader.
The other thing is, we need some kind of init code of the startup servlet
context which allows to setup such custom loaders.
along the lines of
_servletContext.getInitParam("org.apache.myfaces.CustomLoaders");
I will try to prototype all this with the current myfaces trunk.
If all goes well and I can eliminate the classloader we probably should
add those extensions to myfaces 2.0.
I personally like this path because it would allow us to hook in several
scripting engines in the long run without having to revert to
custom classloaders which are a pain in various container configurations.
Anyway what is your opinion about those changes?
Werner