I am not familiar with RMI, but I have looked at the classloaders. The classloader overview is defined in the classloader document. There are two instances of StandardClassLoader that are used by webapps, 'shared' and 'common'. Then each webapp has its own WebappClassLoader instance.
If the WebappClassLoader can not find a class then it delegates to the 'shared' instance of StandardClassLoader, which then can delegate to the 'common' instance. Are you by chance passing a Hashtable,Vector,etc that contain instances of your classes? If so you may want to see this thread from last week which also had a problem serializing objects(although not with RMI): http://www.mail-archive.com/[email protected]/msg61929.html For (2) below: This is difficult because classes loaded by the WebappClassLoader will not know about the classes that you load. This is why you get ClassNotfoundExceptions. It may help to set the current classloader as the parent for your new classloader, so that class requests can be delegated. For (3) below: This is what the WebappClassLoader already does. The webapp specific things are in the /WEB-INF/lib, which you said was returned by getUrls(). I looked at the bug listed previously. does the stack trace change when you have no spaces in the tomcat path? Charlie > -----Original Message----- > From: Greg Trasuk [mailto:[EMAIL PROTECTED]] > Sent: Friday, August 09, 2002 11:54 PM > 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.TestW ebapp.SampleCl > 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:[EMAIL PROTECTED]> > For additional commands, e-mail: > <mailto:[EMAIL PROTECTED]> > -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
