On 12/10/2009 08:42, Adam Monsen wrote:
You don't say which version of Tomcat you're using, but I guess 6.0
from your paths.
Correct. I've tried both 6.0.16 and 6.0.20.
You should take a close look at
http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html .
I read that page before posting to this list, along with other Tomcat
docs, the Tomcat wiki, and the archives of this list.
So you ask for Class.forName("AudiBankImporter"). The webapp
classloader can't load this, so delegates to the common classloader.
The common classloader loads the class and tries to resolve the class'
references to other classes. It tries to resolve the reference to
TransactionImport; can't find it; delegates up the chain; still can't
find it; and fails with the error you see.
Ah! Ok, that totally makes sense. Thank you for this clear interpretation!
If you really, really have to do it this way (and it seems like a
rather odd thing to do), you'll need to ensure that the common
classloader can resolve TransactionImport. This means that you then
should ensure TransactionImport is *not* loaded by your webapp
classloader - you need to move it out of your webapp to
CATALINA_HOME/lib.
My idea was that TransactionImport is the interface (abstract class,
actually) that the webapp authors define and use in webapp code, and
plugin authors need only to implement TransactionImport, provide the
fully-qualified class name of their implementation and put their
compiled implementation somewhere that the Webapp can load.
Ideally, this would be somewhere like $HOME/.mifos/plugins , I was
just trying to simplify things during development by placing plugins
in $CATALINA_HOME/lib for now. Any idea how I could load plugins from
$HOME/.mifos/plugins ? Would it be possible to add jars or classes in
this directory to the classpath at runtime?
I could exclude TransactionImport from the webapp, but I think this
would complicate deployment. I'd have to say something like "to deploy
my webapp you must also place mifos-spi-1.0.jar in
$CATALINA_HOME/lib". Maybe that's not too bad? Makes upgrading the
webapp a bit more of a hassle (more than just dropping in a new war).
Hmm, actually, maybe this will work! It appears I can import and
mention TransactionImport even if it is only available during
compilation (ie: not placed in WEB-INF/lib in the webapp). Ok, cool,
this is looking like the best option so far until I can figure out how
to load plugins from $HOME/.mifos/plugins . Yay!
Equally, you could put the jar containing
AudiBankImporter into your webapp, which seems like a simpler and more
isolated approach unless you're trying to solve a larger problem than
you've described!
I want to release my webapp first, then allow plugin authors to write
and load plugins at their leisure.
Have you looked at the ServiceLoader API?
Perhaps there's a way to automate copying a plugin into WEB-INF/lib
such that it can be used by a webapp?
Probably not a good idea.
I'm sure I'm going about this all wrong, but hopefully I'm getting
closer to something that makes sense.
>
I tried setting<Loader delegate="true"/> in context.xml (based on
http://tinyurl.com/yk7f63k),
That seems to be related to a completely different issue, even if the
outcome seems to help.
and I *am* able to load AudiBankImporter
if I include TransactionImport in the plugin jar. I don't know other
implications of this change, and it seems like a weird thing to have
to require to be able to deploy my webapp.
You *must* include the interface class(es). This is not optional.
I think I covered most of Pid's questions too, except:
* yes, TransactionImport is in a package
* I had been trying to include _and_ exclude TransactionImport in the
plugin jar in $CATALINA_HOME/lib . The first gave me a class cast
exception ("AudiBankImporter cannot be cast to TransactionImport"),
and the second (which we've covered) runs into the
ClassNotFoundException since TransactionImport can't be seen by the
common classloader.
You may experience a ClassCastException if TransactionImport.class is in
two places at the same time.
The interface (and any related classes) should be placed in a jar (say
base.jar).
Anyone implementing the interface (or extending an abstract class) must
ensure that 'base.jar' is available to the ClassLoader that contains
their implementing class.
This means the following:
If the implementing class (in say impl.jar) is in myapp/WEB-INF/lib
then base.jar can be in either the webapp, or $CATALINA_HOME/lib
If impl.jar is in $CATALINA_HOME/lib then base.jar must be there too.
You may *not* put 'impl.jar' in $CATALINA_HOME/lib if 'base.jar' is in
myapp/WEB-INF/lib.
I hesitate to suggest this, as I think you need to understand how the
ClassLoader hierarchy works before proceeding, but...
...if your web app uses a custom ClassLoader that performs as normal,
but looks in a special location for additional plug-in classes, you may
be able to achieve what you want.
N.B. Writing a custom ClassLoader of this sort is not trivial IMHO.
p
P.S. (It is generally advisable to put all of the classes you can in the
web application, rather than in $CATALINA_HOME/lib.)
Thank you both for your help so far, and sorry if this is drifting to
non-Tomcat stuff.
Finally, here's the code I've been experimenting with in case folks are curious.
source for package defining TransactionImport abstract class:
https://mifos.dev.java.net/source/browse/mifos/trunk/spi/
source for package implementing TransactionImport (AudiBankImporter):
https://mifos.dev.java.net/source/browse/mifos/spikes/importPluginExample/
The plugin framework will eventually end up in the Mifos webapp (
https://mifos.dev.java.net/source/browse/mifos/trunk/application ),
but I made a small webapp for testing purposes:
http://adammonsen.com/tmp/smallappwithplugins.tgz
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org