ashur ashur - 5 months ago 23
Java Question

Java: Remote Method Invocation (RMI)

I'm trying to run simple RMI service, where server and client are on the same machine. Unfortunately, each time I try to run server class I get an exception. I keep server and client in seperate folders and I copied needed files to client.

These are the steps that I took:


  1. Add Folder where server files are hold to CLASSPATH.

  2. Start rmiregistry. (As far as I know I no longer need to make stub file Updated with stub files)

  3. Run server. <- Exception

  4. Run client.



Folder hierarchy:

server [AddServerIntf.class, AddServerImpl.class, AddServer.class]
client [AddServerIntf.class, AddClient.class]

Exception

C:\Users\Szymon\Desktop\serwer>java AddServer
Exception: java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
java.lang.ClassNotFoundException: AddServerIntf


Code

The remote interface

import java.rmi.*;

public interface AddServerIntf extends Remote {
double add(double d1, double d2) throws RemoteException;
}


Class which implements interface above

import java.rmi.*;
import java.rmi.server.*;

public class AddServerImpl extends UnicastRemoteObject
implements AddServerIntf {

public AddServerImpl() throws RemoteException {
}
public double add(double d1, double d2) throws RemoteException {
return d1 + d2;
}
}


Class which creates server

import java.net.*;
import java.rmi.*;

public class AddServer {
public static void main(String args[]) {

try {
AddServerImpl addServerImpl = new AddServerImpl();
Naming.rebind("AddServer", addServerImpl);
}
catch(Exception e) {
System.out.println("Exception: " + e);
}
}
}


Client

import java.rmi.*;

public class AddClient {
public static void main(String args[]) {
try {
String addServerURL = "rmi://" + args[0] + "/AddServer";
AddServerIntf addServerIntf = (AddServerIntf)Naming.lookup(addServerURL);
System.out.println("1st: " + args[1]);
double d1 = Double.valueOf(args[1]).doubleValue();
System.out.println("2nd: " + args[2]);

double d2 = Double.valueOf(args[2]).doubleValue();
System.out.println("Sum: " + addServerIntf.add(d1, d2));
}
catch(Exception e) {
System.out.println("Exception: " + e);
}
}
}


The effect with stub file is similar

C:\Users\Szymon\Desktop\serwer>java AddServer
Exception: java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested excep
tion is:
java.lang.ClassNotFoundException: AddServerImpl_Stub

EJP EJP
Answer

The Registry doesn't have your remote interface on its CLASSPATH. IMHO the best solution to this is to run the Registry inside your server JVM, with LocateRegistry.createRegistry().

As far as I know I no longer need to make stub file

Not correct. See the preamble to the Javadoc for UnicastRemoteObject. You would need to provide a super(0) line in your remote object's constructor to satisfy the conditions specified there.