velocity-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Nutter, Charles O." <>
Subject ClassLoader resource loading of templates, for the record (and perhaps for the next release?)
Date Thu, 07 Aug 2003 21:20:57 GMT
(Sorry if this sort of thing should be posted to -dev, but I wanted to toss it out for comments
first :)

I managed to create a resource loader that does what I need to.

I see the following problems with ClasspathResourceLoader:

1. It loads templates using the ClassLoader it was loaded in, which in many cases will be
the top-level or a high-level ClassLoader within an appserver
2. Individual applications within the server almost always are given their own contextual
ClassLoader. In Tomcat, for example, each webapp has its own loader.
3. Each webapp should be able to package templates in jars to be put in WEB-INF/lib and have
Velocity load them correctly.
4. Each webapp should not have to put velocity-xxx.jar in their WEB-INF/lib to be able to
use Velocity.
5. Therefore, Velocity should be able to load templates using the contextual ClassLoader appropriate
for the *caller*

ClasspathResourceLoader uses getClass().getClassLoader() to look for templates. If Velocity
is loaded at the system or server level, and a webapp hopes to use this method to load its
own jarred templates, it will fail as it did for me.

The fix is terribly simple, and I think it makes sense to apply it directly to ClasspathResourceLoader,
or at least provide a ThreadContextResourceLoader, as I have done:

In ClasspathResourceLoader.getResourceStream(), change:

ClassLoader classLoader = this.getClass().getClassLoader();


ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

This will cause the resource loading to look first at the caller's level (webapp) and if not
found, move up the ClassLoader chain. I believe this is the appropriate way to handle loading
templates as resources. From the documentation for getContextClassLoader():

     * Returns the context ClassLoader for this Thread. The context
     * ClassLoader is provided by the creator of the thread for use
     * by code running in this thread when loading classes and resources.
     * If not set, the default is the ClassLoader context of the parent
     * Thread. The context ClassLoader of the primordial thread is
     * typically set to the class loader used to load the application.

The resource should be loaded from the ClassLoader that the creator of the calling thread
intended...not from the system classloader. Also keep in mind this change would not break
loading from the system would just include contextual ClassLoaders in the lookup

Comments? Questions? Flames? What do I have to do to convince the Velocity guys this needs
to go in? :)

- Charlie

View raw message