Monday, June 16, 2008

WTF is wrong with RMI

Yes, WTF is wrong with RMI. Taken from the "Getting Started using RMI" page:

Note: Before you start the rmiregistry, you must make sure that the shell or window in which you will run the registry either has no CLASSPATH set or has a CLASSPATH that does not include the path to any classes that you want downloaded to your client, including the stubs for your remote object implementation classes.

If you start the rmiregistry, and it can find your stub classes in its CLASSPATH, it will ignore the server's java.rmi.server.codebase property, and as a result, your client(s) will not be able to download the stub code for your remote object. For an explanation of how code downloading works in RMI, please take a look at the tutorial on Dynamic code downloading using RMI.

UPDATED: Omg :) That's documentation for 1.4.2. If you refer to the latest one, it actually highlights on the classDir. So ultimately, my problem of not referring to a newer documentation.

Not paying much attention to these lines, it got me wasted a few valuable hours to get a simple example working. I have a Hello interface and a HelloImpl implementation with a main method in it to do the binding.

I kept getting either:

java.lang.ClassNotFoundException: foo.Hello
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)

and

java.lang.ClassNotFoundException: foo.HelloImpl_Stub
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)

Whenever I ran:
java -classpath classes/ foo.HelloImpl

The error is misleading. It made me wondered why Java would complain about ClassNotFoundException when those classes were in the classpath! To put that paragraph in bullet points:

  • Please set the CLASSPATH variable before you run rmiregistry, e.g.
    export CLASSPATH=classes/
    rmiregistry &
    java -classpath classes/ foo.HelloImpl

  • Or, please set the -Djava.rmi.server.codebase system property to point to your classpath when you start your application, e.g.
    rmiregistry &
    java -Djava.rmi.server.codebase=file:classes/ -classpath classes/ foo.HelloImpl

Yes, it was actually my problem of not reading the documentation clearly. But can't just the Java guys fix it so that it will pick up from the classpath without setting either the environment variable or system property?

- yc, rants!!

2 comments:

Anonymous said...

What's wrong?

1) The need to use a separate rmiregistry
2) The weirdness of rmiregistry itself and its lousy docs.
3) RMI's heavy use of sockets in all directions (just thinking about a firewall will likely break it, in hard-to-debug ways)
4) The flaws of it's basic concept of (almost) transparently distributed objects.

But not that the alternatives are much better. HTTP is nice though.

Y said...

The more Java guys I talked with, the more I found how much they dislike about RMI. ;)

I just happened to bump into it again (the first time was a few years back in the Uni.) these days, not for any particular project, but just to see how is it like as I can't remember the time in Uni. I wasn't aware that stubs are no longer required starting 1.5 onwards.

yc