See intermixed.

On Thu, 11 Jul 2002, Will Hartung wrote:

> Date: Thu, 11 Jul 2002 13:52:50 -0700
> From: Will Hartung <[EMAIL PROTECTED]>
> Reply-To: Tomcat Users List <[EMAIL PROTECTED]>
> To: Tomcat Users List <[EMAIL PROTECTED]>
> Subject: Re: Dynamically add jar file to classpath while tomcat is running
>
> From: "KAKARONTZAS GEORGE" <[EMAIL PROTECTED]>
> Sent: Wednesday, July 10, 2002 11:04 PM
>
>
> > Hi all,
> > I'm building a system that must be able to execute any java app that
> > will be uploaded.
> > In fact the server (a web app running under tomcat) just dispatches
> > these applications to other pcs.
> > The problem is that while the server serializes the application class
> > files for dispatching I get a HTTP 500 error on the pcs that want to
> > execute the code.

Without knowing details of the stack trace that you get along with this,
it is impossible to understand what is going on.

> > I'm not getting this if I copy the app files (contained in a jar) in the
> > WEB-INF/lib before starting tomcat.

Why are you bothering to put this stuff inside the webapp?  Wouldn't it be
better to run these uploaded applications under a separate JVM, out of a
separate directory, where you can configure its own class path totally
separate than the one your webapp is running under?

> > So I concluded that the reason for the error is that this jar file is
> > not in the classpath of the web application class loader.
> > First I want to ask if you agree with that.
> > Second, if you do is there a way to add a jar file in the web
> > application class loader classpath, while the application is running.
> > Note that I modified the code so that the jar file is copied in
> > WEB-INF/lib after uploading, but that didn't work.
>
> I can't say about the 500 error, as that can be most anything.
>
> But, let's discuss the Jar file issue.
>
> The problem with the Jar file is that it must physically appear on the
> CLASSPATH of the ClassLoader for it to be considered, and I don't know of a
> way to dynamically update the CLASSPATH that would actually affect the
> ClassLoader. In theory you might be able to simply change the
> java.class.path System property, but I'd be very surprised if that worked. I
> would think that the ClassLoader would only read that when it's instantiated
> and pretty much ignore it afterward.
>

Technically, there is one and only one CLASSPATH environment variable, and
one and only one corresponding "java.class.path" system property, for the
entire container.  That is obviously not useful in setting up
individualized environments for each web application, so Tomcat basically
ignores it.

Instead, Tomcat builds a hierarchy of class loaders, and offers you places
to put JAR files that you want to share across webapps.  Online docs are
at:

  http://jakarta.apache.org/tomcat/tomcat-4.0-doc/class-loader-howto.html

or

  http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html

depending on your version.  For example, any JAR file that you put in
$CATALINA_HOME/common/lib will be visible to all web applications.

> One solution, though, is to reserve an actual directory that is on the
> CLASSPATH and then rather than simply copying the Jar files, actually
> explode them into that directory. Java's default ClassLoaders seem to pick
> up new classes within directories that already exist on the CLASSPATH.
>
> So, if a Jar was exploded into a directory already on the CLASSPATH (i.e.
> being monitored by the Java ClassLoaders), then, in theory, those classes
> would be dynamically loadable into a running JVM.
>

As described above, you cannot use CLASSPATH in a container because it is
global to the JVM.  Of course, that is one of the reasons I suggested
above that perhaps the uploaded apps should be run in their own JVMs.

> Now, of course, you will have a problem RE loading those applications and
> classes without a restart, but that's a different topic.
>

That's why it is generally recommended to put JAR files inside your webapp
-- then they can be reloaded with just that webapp instead of requiring a
complete restart of the container.

> Finally, this is all designed to work around the existing ClassLoaders. The
> real solution is to write your own ClassLoader, and solve it that way.
>
> In the 3.2 Tomcat, there's a file
> org.apache.tomcat.loader.AdaptiveClassLoader (I don't have the 4.x source
> handy). That can serve as an inspiration.
>

There is such a class loader, of course
(org.apache.catalina.loader.WebappClassLoader), but let me give you a few
words of caution based on my own experience implementing Tomcat 4 -- class
loaders are black magic.  Anyone who thinks this is going to be a minimal
effort approach is going to be very rudely surprised by the complexity.

And, even if you go to all of that work, you are most likely going to find
something like this happenening to you:

* You run your container under a security manager, and trying
  to create the new classloader throws a security exception

* You do something that totally screws up class loading for the
  entire container, and you're on your own fixing it.

* You find yourself spending a significant percentage of time
  building and maintaining your custom container modifications,
  instead of building and maintaining your applications.

You are very much better off adapting your application architecture
to what your container supports, instead of spending time and effort
remodelling the container itself.

> Best Regards,
>
> Will Hartung
> ([EMAIL PROTECTED])
>

Craig


--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to