views:

573

answers:

2

Hi, I have an RMI client/server set-up on two machines that works fine in a simple situation when the server doesn't require a client-side defned class. However, when I need to use a class defined on the client side I am unable to have the server unmarshall those classes. I suspect this is an issue with my java.rmi.server.codebase property that I pass in as argument to the client app. I followed Sun's RMI Tutorial trail and I think I have followed the steps exactly except that I don't specify a classpath argument when executing client and server because they execute in the directory right above the root package directory (however I tried that too with no effect).

The exceptions I get when attempting to execute the different client-side combinations described in detail below are all the same:

RmiServer exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: java.lang.ClassNotFoundException: test.MyTask at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:353) at sun.rmi.transport.Transport$1.run(Transport.java:177) at java.security.AccessController.doPrivileged(Native Method) at sun.rmi.transport.Transport.serviceCall(Transport.java:173) at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808) at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:636) at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255) at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233) at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142) at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178) at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132) at $Proxy0.execute(Unknown Source) at test.myClient.main(myClient.java:32)

The details are:

My client/server rmi is set up over a home network behind a router. The router is assigned to a static ip address I will call myhostname. Appropriate port-mapping is set-up in the router that points to the right machines.

role, machine, os, ip-address:

server, venice, linux ubuntu 9.10, 10.0.1.2
client, naples, mac os x leopard, 10.0.1.4

I startup the server side as follows inside /home/andrews/workspace/epsilon/bin:

1 starting registry on the default port 1099:

venice% rmiregistry &

2 starting web-server on port 2001 pointing to code base for common interfaces:

venice% java webserver/ClassFileServer 2001 /home/andrew/workspace/epsilon/bin

3 starting server app (main class in test/myServer) which registers the server object:

venice% java -Djava.rmi.server.codebase="http://myhostname:2001/" -Djava.security.policy=server.policy -Djava.rmi.server.hostname=myhostname test/myServer &

Now the client side inside /Users/andrews/Development/Java/workspace/epsilon/bin:

1 start a local web server that can server client-side classes to the server (not sure if this is needed, but I added I tried it, and still no success; I have added port-mapping to the router for 2001 to venice, for 2002 to naples)

naples$ java webserver/ClassFileServer 2002 /Users/andrews/Development/Java/workspace/epsilon/bin/

Trying to run the client (note: I don't specify the -cp argument because client executes right above the root package directory):

1 try #1 using an http hostname

naples$ java -Djava.rmi.server.codebase=http://10.0.1.4:2002/ -Djava.security.policy=client.policy test.myClient myhostname

Note 1: the myhostname argument at the end is passed-in to the client so that it resolves to server's rmi hostname.

Note 2: I tried using localhost:2002 instead of 10.0.1.4:2002 too.

Note 3: I tried using myhostname:2002 since myhostname is assigned to the router and I have proper port-mapping set-up, this address should resolve to naples and not venice

2 try #2:

naples$ java -Djava.rmi.server.codebase=file:/Users/andrews/Development/Java/workspace/epsilon/bin/ -Djava.security.policy=client.policy test.myClient myhostname

Note 1: the code base url format is correct, I created a small program to convert current file directory path into a url and used that. using file:///Users... has same effect.

Other notes:

1 my server and client policy files correctly specify the path, as I've tested this setup with good and bad paths, and getting a security exception for bad path

2 this setup works if I don't use client-side defined objects, the client connects correctly to the server and the server executes.

3 when I place the client-side class on the server in the server's classpath, all executes fine.

All help is appreciated.

A: 

Do you really need to use RMI? Me and a friend tried it once in school and it was way slow, much slower then the simple ObjectOutputStream networking we had been doing earlier.

Chad Okere
Thanks for the suggestion, I'll try that out.
andrewz
A: 

I strong agree with Chad Okere's said, RMI is really very slow and consuming-resouces. sometimes directly use Sockets maybe is simple and useful chooice, regarding your exception Could you confirm your rmi server work correctly? http://www.javarmi.com/2010/05/java-rmi-error-unmarshalling-arguments/ maybe be can help you

josh tsr