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]>
