Thanks for your comments Greg. Now at least I know what's going on. I'm
going to attach these comments to the bug log.

Thanks.
Dave.

> -----Original Message-----
> From: Greg Trasuk [mailto:[EMAIL PROTECTED]]
> Sent: 10 August 2002 04:54
> To: 'Tomcat Users List'
> Subject: RE: RMI and TC4.x (Really classloader stuff)
> 
> Hi David:
> 
>       I'm in the same boat trying to use RMI and/or Jini from Tomcat.
> This isn't
> a complete answer to your question, as I'm still investigating the issue,
> but I'm posting what I know so far in the hope that it might help in your
> own solution, and also generate discussion that will guide my exploration.
> When all is said and done, if there's interest, I can post a "Catalina-RMI
> HOWTO" sort of document.
> 
>       Although I didn't try to run the test case that you attached to your
> bug
> report, I did take a look at it, and I think I know what's going on.
> Here's
> what I know so far (most of which you probably know already, but I'm
> summarizing for other folks on the list):
> 
>       When you pass an instance of some Serializable class as an argument
> to an
> RMI call (e.g. passing a command object, as in your test case), the RMI
> subsystem will serialize the object with an additional annotation
> indicating
> the locations from which the class's bytecode can be downloaded.  When you
> pass an exported object (e.g. a server object or an object that will
> receive
> callbacks from remote objects), the RMI subsystem creates and serializes a
> proxy object (otherwise known as the RMI stub object) in place of the
> actual
> object.  In either case, the remote RMI subsystem has to load the class
> that
> is called out in the serialized instance.  It does this by calling the
> RMIClassLoader.
> 
>       The RMIClassLoader object first tries to find the class locally
> (i.e. in
> the default classloader).  If it can't find it locally, it searches in the
> list of locations contained in the annotation mentioned above.  If the
> required class is available locally, no further headaches are caused,
> which
> may be why some people have had no problems using RMI under Tomcat - they
> probably had the serialized classes and/or proxy classes in the standard
> classpath/classloader setup.
> 
>       And there we find our problem.  (At this point you might want to
> have a
> look at the JSP snippet below) The annotation is determined by
> RMIClassLoader. According to the "RMI and Object Serialization FAQ" in the
> JDK1.31 API docs,
> 
>   "If the _Stub class was loaded by an RMIClassLoader, then RMI already
> knows which codebase to use for its annotation. If the _Stub class was
> loaded from the CLASSPATH, then there is no obvious codebase, and RMI
> consults the java.rmi.server.codebase system property to find the
> codebase.
> If the system property is not set, then the stub is marshalled with a null
> codebase, which means that it cannot be used unless the client has a
> matching copy of the _Stub classfile in the client's CLASSPATH. "
> 
>       If we're running a standalone application (and I believe also in
> Tomcat
> 3.x), we're using the system class loader, which has "no obvious
> codebase",
> so the java.rmi.server.codebase property gets used.  But what's the class
> loader used in Tomcat 4.x?  I looked at the source code for Tomcat 4.0.1
> (happens to be what I have on hand), and o.a.c.loader.WebAppClassLoader
> extends from o.a.c.loader.StandardClassLoader, which extends from
> java.net.URLClassLoader, which has a method called getURLs().  The
> WebAppClassLoader.getURLs() method returns a list of all the repositories
> it
> will search when trying to load a class on behalf of the web app.  This
> list
> calls out all the jar's in WEB-INF/lib, common/lib, etc.
> 
>       Having not seen the source for RMIClassLoader, I suspect that the
> getClassAnnotation(..) method checks to see if the classloader for the
> supplied class is a URLClassLoader, and if so, uses the results of the
> getURLs() method call as "an obvious codebase".  This suspicion is
> supported
> by the last part of the JSP, where I create a classloader that extends
> from
> URLClassLoader but overrides getURLs() to return a phony url.  The phony
> url
> shows up as the class's annotation.
> 
>       So the exact error you quoted in the bug report shows something
> about a
> "protocol missing" MalformedURL exception, which is caused by the fact
> that
> the urls to the repositories contain spaces, since the RMI annotation is
> supposed to be a "space-separated list of URL's".  Thus the annotation
> doesn't get parsed properly.   This may be a bug in Catalina's class
> loader
> (i.e. should the returned urls have the spaces encoded to '%20'?) or
> possibly in the way RMIClassLoader uses the results of getURLs().  But
> it's
> not the problem.
> 
>       The problem is how to get our codebase into the annotation.  Clearly
> the
> java.rmi.server.codebase property is not used, since the class loader has
> a
> codebase.  But setting a system property doesn't feel right to me anyway,
> since in a webapp scenario, we're in a shared JVM, and we shouldn't be
> allowed to set system properties that will affect other webapps.  (Aside-
> we
> similarly can't follow the normal practise of setting our own
> RMISecurityManager, again since it doesn't play nice with the other
> webapps.
> When I tried it, it seemed to screw-up Tomcat's internals, as well.  We
> need
> to run Tomcat with security enabled, and set the appropriate permissions).
> 
>       Options as I see them:
>       (1)-Use an object factory approach to create instances of classes.
> If we
> get the factory object from the RMI server, it and all the instances it
> creates will have the server's codebase property already set, which skirts
> the whole issue.  It won't allow us to use locally-defined inner classes,
> however, so it's not great for callback objects (although I suspect we
> could
> have the created object call back to a local object)
> 
>       (2)-Load our local classes explicitly through a classloader that
> returns
> our codebase.  This is what I did in the last part of the test case.  It
> seems like a pain in the butt, and also caused ClassCastExceptions, which
> is
> why the reference is to an Object.
> 
>       (3)-Replace the context's classloader with a class loader that adds
> a
> webapp-specific codebase to the repositories it lists.  I'm thinking of
> having a property defined in the application context to specify the
> codebase.  There's already provision in server.xml to specify an alternate
> webapp classloader. Downside is that the application is then Tomcat-
> specific
> (not that anyone would want to use any other container...).
> 
>       I suspect that using RMI purely as a client (i.e. with no local
> objects
> exported) and passing only instances of classes on the local classpath of
> both client and server (e.g. java.* classes) would work just fine, with no
> codebase issues at all, but I've yet to try it out.
> 
>       Ideas and comments, anyone?
> 
> 
> 
> Greg Trasuk, President
> StratusCom Manufacturing Systems Inc. - We use information technology to
> solve business problems on your plant floor.
> http://stratuscom.ca
> 
> 
> <test-case apology="I know it's ugly code">
> 
> <%@page import="ca.stratuscom.TestWebapp.SampleClass" %>
> <%@page import="java.rmi.server.RMIClassLoader" %>
> <%@page import="java.util.Date" %>
> <%@page import="java.rmi.RMISecurityManager" %>
> <%@page import="java.net.URL" %>
> <%@page import="java.net.URLClassLoader" %>
> 
> <%!
> private class MyLoader extends URLClassLoader {
>   public URL[] getURLs() {
>     URL retval=null;
>     try { retval=new URL("http://bob/fred.jar";); }
>     catch (Exception e) {}
>     return new URL[] {
>       retval
>       };
>   }
> 
>   MyLoader(URL urls[]) { super(urls); }
> }
> %>
> 
> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
> <html>
>   <head>
>     <title></title>
>   </head>
> 
>   <body>
>     <h1>Show Annotation for locally created class</h1>
>       <%
>     /* System.setSecurityManager(new RMISecurityManager()); */
> 
>     String codebase="http://localhost:8080/TestWebapp/TestWebapp.jar";;
>       Date dt=new Date();
>     /*System.setProperty("java.rmi.server.codebase",codebase);*/
>       String annotation=RMIClassLoader.getClassAnnotation(dt.getClass());
>       SampleClass sample=new SampleClass();
>       String sampleAnnotation=
>               RMIClassLoader.getClassAnnotation(sample.getClass());
>       %>
>       Annotation for a Date instance is <%=annotation%>.
> <br>
>       Annotation for a SampleClass instance is <%=sampleAnnotation%>.
>     <hr>
>     <%
>     Class
> sampCls=RMIClassLoader.loadClass(codebase,"ca.stratuscom.TestWebapp.Sample
> Cl
> ass");
>     SampleClass rmiSamp=(SampleClass) sampCls.newInstance();
>     String localSampAnnotation=
>               RMIClassLoader.getClassAnnotation(rmiSamp.getClass());
>     %>
>     <br>
>     Annotation for localSamp loaded through RMIClassLoader is
>     <%=localSampAnnotation%>
>     <hr>
> 
>     <%
>     URL codebaseURL=new URL(codebase);
>     URL loaderURLs[]=new URL[] {codebaseURL};
>     URLClassLoader urlLoader=new URLClassLoader(loaderURLs);
> 
>     Class
> urlCls=urlLoader.loadClass("ca.stratuscom.TestWebapp.SampleClass");
>     Object urlSamp= urlCls.newInstance();
>     String urlSampAnnotation=
>               RMIClassLoader.getClassAnnotation(urlSamp.getClass());
>     %>
>     <br>
>     Annotation for localSamp loaded through URLClassLoader is
>     <%=urlSampAnnotation%>
>     <hr>
> 
>     <%
>     MyLoader myLoader=new MyLoader(loaderURLs);
> 
>     Class
> myCls=myLoader.loadClass("ca.stratuscom.TestWebapp.SampleClass");
>     Object mySamp= myCls.newInstance();
>     String mySampAnnotation=
>               RMIClassLoader.getClassAnnotation(mySamp.getClass());
>     %>
>     <br>
>     Annotation for localSamp loaded through MyLoader is
>     <%=mySampAnnotation%>
>     <hr>
> 
>     <address><a href="mailto:trasukg@THINKPAD";></a></address>
> <!-- Created: Wed Jul 31 09:17:33 Eastern Daylight Time 2002 -->
> <!-- hhmts start -->
> Last modified: Fri Aug 09 01:01:14 Eastern Daylight Time 2002
> <!-- hhmts end -->
>   </body>
> </html>
> 
> -- In SampleClass.java
> package ca.stratuscom.TestWebapp;
> 
> public class SampleClass {}
> </test-case>
> 
> >-----Original Message-----
> >From: David Oxley [mailto:[EMAIL PROTECTED]]
> >Sent: July 23, 2002 05:36
> >To: 'Tomcat Users List'
> >Subject: RE: RMI and TC4.x
> >
> >
> >It does actually connect to the RMI server, but it can't
> >download classes
> >from the web server. It looks like java.rmi.codebase = TC
> >local path rather
> >than http://server/webapp which iks what the code sets it to.
> >
> >Dave
> >
> >> -----Original Message-----
> >> From: Shapira, Yoav [mailto:[EMAIL PROTECTED]]
> >> Sent: 22 July 2002 18:25
> >> To: Tomcat Users List
> >> Subject: RE: RMI and TC4.x
> >>
> >> Howdy,
> >> We use RMI extensively on long-running tomcat servers (4.0.1
> >and 4.0.4).
> >> Never had any problems with it.  We even have a portion of the night
> >> when we do very frequent (more than 1/sec) serialization and
> >> deserialization of relatively large, complex (but
> >serializable) objects
> >> between a number of servers.
> >>
> >> We also use JDK 1.4.0 (also tested on 1.3.1), on Solaris.  I
> >looked at
> >> your bugzilla bug report, and it looked like a fairly simple
> >> MalformedURLException.  I wonder if this bug is related to a
> >difference
> >> between tc 3.x and 4.x in the way they handle spaces in
> >JNDI/RMI server
> >> URLs.  Did you try using tomcat 4.x to connect to an RMI server that
> >> doesn't have a space in its URL?
> >>
> >> Yoav Shapira
> >> Millennium ChemInformatics
> >>
> >>
> >> >-----Original Message-----
> >> >From: David Oxley [mailto:[EMAIL PROTECTED]]
> >> >Sent: Monday, July 22, 2002 12:59 PM
> >> >To: 'Tomcat Users List'
> >> >Subject: RMI and TC4.x
> >> >
> >> >Has anyone got RMI working from within TC4.x. I had no
> >problems under
> >> >TC3.x,
> >> >but just can't get it working under TC4.x.
> >> >
> >> >I have had a bug report outstanding for quite some time on
> >this, but I
> >> was
> >> >hoping that someone on the user list may have already got
> >this working.
> >> >
> >> >http://issues.apache.org/bugzilla/show_bug.cgi?id=7082
> >> ><http://issues.apache.org/bugzilla/show_bug.cgi?id=7082>
> >> >
> >> >
> >> >
> >> >Cheers.
> >> >
> >> >Dave.
> >>
> >>
> >> --
> >> To unsubscribe, e-mail:   <mailto:tomcat-user-
> >> [EMAIL PROTECTED]>
> >> For additional commands, e-mail: <mailto:tomcat-user-
> >> [EMAIL PROTECTED]>
> >
> >--
> >To unsubscribe, e-mail:
> <mailto:[EMAIL PROTECTED]>
> For additional commands, e-mail:
> <mailto:[EMAIL PROTECTED]>
> 
> 
> --
> To unsubscribe, e-mail:   <mailto:tomcat-user-
> [EMAIL PROTECTED]>
> For additional commands, e-mail: <mailto:tomcat-user-
> [EMAIL PROTECTED]>

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

Reply via email to